views:

111

answers:

3

I used this command to find mp3 files and write their name on log.txt:

find -name *.mp3 >> log.txt

I want to move the files using the mv command and I would like to append that to the log file so it could show the path where the files have been moved.

For example if the mp3 files are 1.mp3 and 2.mp3 then the log.txt should look like

1.mp3 >>>> /newfolder/1.mp3 

2.mp3 >>>> /newfolder/2.mp3

How can I do that using unix commands? Thank you!

+1  A: 

You should probably use some scripting language like Perl or Python; text processing is rather awkward in the shell.

E.g. in Perl you can just postprocess the output of find, and print out what you did.

#!/usr/bin/perl -w

use strict;
use File::Find;

my @directories_to_search=("/tmp/");

sub wanted {
  print "$File::Find::name >>> newdir/$_\n";
  # do what you want with the file, e.g. invoke commands on it using system()
}

find(\&wanted, @directories_to_search);

Doing it in Perl or similar makes some things easier than in the shell; in particular handling of funny filenames (embedded spaces, special chars) is easier. Be careful when invoking syste() commands though.

For docs on the File::Find module see http://perldoc.perl.org/File/Find.html .

sleske
wrong. text processing is not awkward in shell, if you know your shell scripting well.
ghostdog74
I'd love be proved wrong, it's just that I've had to maintain thousands of LOC of shell scripts implementing an order processing system, and found it extremely painful. Fancy trying to give an answer with a shell script example?
sleske
Thank you very much!
jualin
+1  A: 

GNU find

find /path -type f -iname "*.mp3" -printf "%f/%p\n" | while IFS="/" -r read filename path
do 
    mv "$path" "$destination"
    echo "$filename >>> $destination/$filename "  > newfile.txt
done

output

$ touch 'test"quotes.txt'
$ ls -ltr
total 0
-rw-r--r-- 1 root root 0 2009-11-20 10:30 test"quotes.txt
$ mkdir temp
$ ls -l temp
total 0
$ find . -type f -iname "*\"*" -printf "%f:%p\n" | while IFS=":" read filename path; do mv "$filename" temp ; done
$ ls -l temp
total 0
-rw-r--r-- 1 root root 0 2009-11-20 11:53 test"quotes.txt
ghostdog74
This shows all files in the destination directory, not just those that have been moved there. Maybe that's what he wants, but maybe not.
Mark Byers
You just proved my point: Your script will fail for filenames that contain a quotation mark ("). That's why I don't like shell scripting :-(.
sleske
@sleske, you sure? i just tested it, its ok.
ghostdog74
Thank you for the response.
jualin
@ghostdog74: Hey, you changed your code. The *IFS=":"* wasn't there before. Anyway, now it does work for names with " in them, but now it fails for names with ":" in them (which are legal under Linux). I fear you just proved my point yet again...
sleske
gosh, you are so pedantic. that ":" is just a delimiter to separate filename and path for the while loop. You can change it any character that should not conflict with filenames. How about a forward slash? is it ok for you? a forward slash is illegal for a file name
ghostdog74
+3  A: 

Using only move:

mv -v *.mp3 tmp/ > log.txt

or using find:

find -name '*.mp3' -exec mv -v {} test/ >> log.txt \;
Mark Byers
That was exactly what I wanted thank you very much. The verbose move command worked like a charm.
jualin