How do I use find to copy all found files to a new name in their same directories?
Solution 1
This solution is probably the most portable:
find "../content" -name "*_compressed.swf" -exec sh -c 'cp {} `dirname {}`/`basename {} compressed.swf`content.swf' \;
There is also the famous rename.pl script which is distributed with Perl, and the rename command which could have made this a bit easier. These aren't available on all distributions though, these commands are for the most part.
Solution 2
I'm sure this all can be handled in one line. I got really close to a one line solution and with some help even closer, but no success. The following works:
#!/bin/bash
# Read all file names into an array
FilesArray=($(find "../content" -name "*_compressed.swf"))
# Get length of an array
FilesIndex=${#FilesArray[@]}
# Use for loop read all directory names
for (( i=0; i<${FilesIndex}; i++ ));
do
source="${FilesArray[$i]}"
destination="$(echo "${source}" | sed 's/compressed/content/')"
cp "${source}" "${destination}"
done
exit 0;
Related videos on Youtube
Michael Prescott
Updated on September 17, 2022Comments
-
Michael Prescott over 1 year
I've got a simple command that does almost what I want. The following will locate all files with a suffix of '_compressed.swf' and copy each into its same directory with a '.bak2' appended:
find '../content' -name '*_compressed.swf' -print0 | xargs -0 -I {} cp {} {}.bak2
Results
In: /content/somefile_compressed.swf
Out: /content/somefile_compressed.swf.bak2However, I need to replace '_compressed.swf' with '_content.swf' I'd like to use find, rather than recursive flag on cp for consistency.
Objective
In: /content/somefile_compressed.swf
Out: /content/somefile_content.swf-
Admin about 14 yearsCross-posted here: serverfault.com/questions/115880/…
-
-
Michael Prescott about 14 yearsThe above moves the files from their current location to the script's location and adds the suffix 'content.swf'. Replacing mv with cp gets me closer, but I still need replace text in name rather than append. I'm getting closer by using sed, but still learning.
-
John T about 14 years@Michael you're right! whoops. I was only testing in the current directory hence why it worked for me. I've fixed it :)
-
Michael Prescott about 14 yearsHey, thanks John. I like it. Much of this is all new to me. I understand usage of find, -exec, sh, dirname {}, basename {}, but I'm a little confused about the combined usage. sh -c ' ' converts the string into a command and runs the command, right? mv {} expands into one of find results "mv ../content/file1of20_compressed.swf ???????" It's the second part of that which I don't understand yet. What is causing the compressed.swf to be replaced by content.swf? In my solution you can see I just learned how to use sed.
-
John T about 14 years@Michael what's happening is the file is being moved with a new name. If
{}
contained/etc/somefile_compressed.swf
, dirname takes/etc
andbasename {} compressed.swf
will leave you withsomefile_
. Now you put these 2 together with the slash I added in the middle (/
) and you have/etc/somefile_
. You'll notice I addedcontent.swf
to the end so it completes the statement as/etc/somefile_content.swf
. HTH. -
quack quixote about 14 yearsi'd use rename.pl if mv functionality was desired (it's not hard to add to any system with Perl) but the cp makes this a different beast. you'd have to tweak the script to do a copy instead of rename, which would work, but is more work. @John - nice find solution; it's big and long and ugly, but it looks like it would work. (don't ask me to help test it tho!) :)