Reputation: 129
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
Upvotes: 5
Views: 5563
Reputation: 8398
If you have Bash 4, you can use globstar
to enable recursive filename expansion (i.e. matches files in subdirectories as well)
shopt -s globstar
for i in **/*.jpg; do cp "$i" "${i%%.jpg}1.jpg"; done
p/s: I added quotes around the arguments for cp
in case there are spaces in filenames or whatnot.
Upvotes: 2
Reputation: 332816
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.
Upvotes: 6