3

I have a bunch of subdirectories with nested directories that have files with the name

output.txt

. I would like to rename all those files to

output_modified.txt

I tried

find . -type f -name "output.txt" -execdir rename 's/output\.txt/output_modified\.txt/' '{}' \;

but it gives the error

rename: not enough arguments

What arguments am I missing or is there a better way to do what I need?

Ddavid
  • 31

2 Answers2

3

You don't need rename here, just do:

find .  -name output.txt -type f -execdir mv -T output.txt output_modified.txt ';'

The -T is a GNU extension. Without it a mv output.txt output_modified.txt could rename output.txt to output_modified.txt/output.txt if there was already a directory called output_modified.txt.

Here rename could be useful in that it can rename more than out file at once, so could make it more efficient than calling one mv per file, but you'd need:

  1. to make sure your rename is one of the perl-based ones, not the dumb one in util-linux. It's sometimes called file-rename or prename or perl-rename.

  2. Invoke it as:

    find . -name output.txt -type f -exec rename '
     s|\.txt\z|_modified.txt|' {} +
    

With the {} + form so find passes more than one at a time to rename.

Some variants of perl-based renames can also take the list of files to rename NULL delimiited on stdin, so with those, you could also do:

find . -name output.txt -type f -print0 |
  rename -0 's|\.txt\z|_modified.txt|'
-1

IMO rename, find, etc. are confusing and hard to use. I find this type of thing easier with mv, https://github.com/sharkdp/fd and GNU Parallel.

fd output.txt | parallel --dry-run mv {} {.}_modified.txt

parallel runs the command you give for each line of whatever you pipe in (in this case fd will give a list of paths). {} means "the current input". {.} means the current input, but with extension removed. --dry-run will just print the commands that parallel would run, without seeing them. You should run this first, and then run without the --dry-run once you are satisfied.

You do have to install fd and parallel from your package manager.