1

I was recently trying to go through a directory recursively and copy all the files named file.jpg to newfile.jpg in the same local directory as the original.

I found a way to do that but it's a bit cumbersome and I have reasons to believe it is probably not the best way to go. I thought I would ask before putting this into a script.

Here is what I have so far:

cd top_of_source_dir
#copy all file.jpg and append 'newfile.jpg' to the name
find ./ -type f -name file.jpg -exec cp '{}' '{}newfile.jpg' \;

#rename the newly created files to 'newfile.jpg'
find ./ -type f -name 'file.jpgnewfile.jpg' -exec rename file.jpgn n '{}' \;

Does anyone have a recipe to do that in one iteration of the source directory?

4
  • 1
    You probably want for f in *.jpg; do echo "$f" "new${f%.*}.jpg"; done Change echo to mv if you are sure the output is correct. Commented May 15, 2017 at 19:42
  • @val0x00ff This doesn't do a recursion through the source directory, does it? My file can be several levels into the source directory. Commented May 15, 2017 at 20:05
  • # Jacques Gaudin, no it doesn't but youc an do something like like find ./ -type f -name '*.jpg' -exec bash -c 'for f; do n="new${f##*/}"; echo "$f" -> "${f%/*}/$n"; done' _ {} + Again replace echo by 'mv` if you thinkk the result is correct Commented May 15, 2017 at 20:26
  • Also don't forget to remove the -> I put there. It was just to visualize the action Commented May 15, 2017 at 20:32

1 Answer 1

1

Here's a simple answer:

find -type f -name file.jpg -print -printf '%h/newfile.jpg\n' | xargs -n2 -d'\n' mv

This makes find generate two lines per matching entry: old file path and new file path (with %h replaced with the directory path).

xargs then executes mv on every two consecutive lines:

  • -d'\n' specifies that elements of the input stream are newline-separated, which is the case here;
  • -n2 specifies that xargs should read two elements at a time and pass it to the command: if two elements are foo and bar, then xargs will run mv foo bar, and then read the next pair, and repeat.

Replace mv with echo mv to see what commands will it actually execute.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks I had xargs in the back of my mind but I am not familiar with it.
@JacquesGaudin Well you should be because it's very powerful :)
@JacquesGaudin I added a description of the options I use.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.