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

In: /content/somefile_compressed.swf
Out: /content/somefile_compressed.swf.bak2

However, I need to replace '_compressed.swf' with '_content.swf' I'd like to use find, rather than recursive flag on cp for consistency.

In: /content/somefile_compressed.swf
Out: /content/somefile_content.swf


3 Answers 3


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.

  • The 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. Feb 23, 2010 at 22:00
  • @Michael you're right! whoops. I was only testing in the current directory hence why it worked for me. I've fixed it :)
    – John T
    Feb 24, 2010 at 4:19
  • Hey, 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. Feb 24, 2010 at 17:53
  • 2
    @Michael what's happening is the file is being moved with a new name. If {} contained /etc/somefile_compressed.swf, dirname takes /etc and basename {} compressed.swf will leave you with somefile_. Now you put these 2 together with the slash I added in the middle (/) and you have /etc/somefile_. You'll notice I added content.swf to the end so it completes the statement as /etc/somefile_content.swf. HTH.
    – John T
    Feb 24, 2010 at 22:54
  • i'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!) :) Feb 24, 2010 at 23:45

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:


# Read all file names into an array
FilesArray=($(find "../content" -name "*_compressed.swf"))

# Get length of an array

# Use for loop read all directory names
for (( i=0; i<${FilesIndex}; i++ ));
    destination="$(echo "${source}" | sed 's/compressed/content/')"
    cp "${source}" "${destination}"

exit 0;

I believe this should do the trick and is collapsible to a one liner if you really really need to ;)

find ../content -name '*_compressed.swf' | while read file
cp "$file" "${file/_compressed.swf/_content.swf}"

Bash pattern substitution works nicely in these cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.