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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With