How do I use find to copy all found files to a new name in their same directories?

9,322

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;
Share:
9,322

Related videos on Youtube

Michael Prescott
Author by

Michael Prescott

Updated on September 17, 2022

Comments

  • Michael Prescott
    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.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.

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

  • Michael Prescott
    Michael Prescott about 14 years
    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.
  • John T
    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
    Michael Prescott about 14 years
    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.
  • John T
    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 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.
  • quack quixote
    quack quixote about 14 years
    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!) :)