Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash, run script on every .jpg file in a directory with subdirectories

Tags:

bash

unix

I have some working code, it's very simple - it copies every *.jpg file, renames it into *1.jpg, no worries.

for i in *.jpg; do cp $i ${i%%.jpg}1.jpg;  done

how can I run this, so that it works on every file in a directory, every file in the subdirectories of that directory

example directory structure:

    test/test1/test2/somefile.jpg
    test/anotherfile.jpg
    test/test1/file.jpg
etc
like image 216
user1051532 Avatar asked Nov 05 '12 03:11

user1051532


1 Answers

The command to do anything recursively to a directory structure is find:

find . -name "*.jpg" -exec bash -c 'file="{}"; cp "$file" "${file%%.jpg}1.jpg"' \;

Using -exec instead of for i in $(find ...) will handle filenames that contain a space. Of course, there is still one quoting gotcha; if the filename contains a ", the file="{}" will expand to file="name containing "quote characters"", which is obviously broken (file will become name containing quote and it will try to execute the characters command).

If you have such filenames, or you might, then print out each filename separated with null characters (which are not allowed in filenames) using -print0, and use while read -d $'\0' i to loop over the null-delimited results:

find . -name "*.jpg" -print0 | \
    (while read -d $'\0' i; do cp "$i" "${i%%.jpg}1.jpg";  done)

As with any complex command like this, it's a good idea to test it without executing anything to make sure it's expanding to something sensible before running it. The best way to do this is to prepend the actual command with echo, so instead of running it, you will see the commands that it will run:

find . -name "*.jpg" -print0 | \
    (while read -d $'\0' i; do echo cp "$i" "${i%%.jpg}1.jpg";  done)

Once you've eyeballed it and the results looks good, remove the echo and run it again to run it for real.

like image 155
Brian Campbell Avatar answered Sep 28 '22 15:09

Brian Campbell