Using the command line (in Fedora) I'd like to rename all the files in the current directory, that have "foo" for the extension, to the same name but with foo1 for the extension.

I've tried several examples found on StackExchange:

rename foo foo1 *.foo


find . -name '*.foo' -execdir rename 's/\.foo$/.foo1/' \{} \;

Both generate the following error multiple times:

rename: not enough arguments

Any ideas appreciated.

  • 1
    What is the result of just find . -name '*.foo'? Your not enough arguments may be from the fact that *.foo expands to nothing (no files match that pattern) so rename complains because you only gave it 1 args. Aug 10 '18 at 19:25
  • 1
    You also may want to check man rename. Not all renames work that way. The rename on Debian stretch expects a perl expression and a list of files to apply it to: rename 's/\e.foo$/foo1/' *.foo Aug 10 '18 at 19:28
  • That does seem to be the error message you'd get from the util-linux "version" of rename (known as rename.ul on some systems) when *.foo expands to nothing - although in many shells, that would require non-default globbing behavior (bash shopt -s nullglob or zsh setopt null_glob for example) Aug 10 '18 at 23:00

Your use of rename might not work everywhere. Another way to achieve this is to use find, mv, and some bash substitution.

find . -name '*.foo' -exec bash -c 'mv "$0" "${0%.foo}.foo1"' "{}" \;

A few things to note:

I use -exec and not -execdir. The latter effectively cds to the directory of the matched file (which isn't what you want, because then the path to the file--which will be relative to .--will no longer be correct). You want just -exec which will run the given command for each file that matches -name '*.foo' (replacing {} with the path to the matched file).

"${0%.foo}" strips the extension .foo so if $0 is "hello.foo" then "${0%.foo}" ends up as "hello". Then adding .foo1 to the end just appends that, so "${0%.foo}.foo1" is "hello.foo1".


Use a for loop

for f in *.foo
    mv $f ${f/.foo/.foo1}
  • This would rename a file called file.foo-something.foo to file.foo1-something.foo. Better to use "${f%.foo}.foo1".
    – Kusalananda
    Aug 10 '18 at 20:23
  • Thanks Kusalananda. However, your pattern changed foo.foo-x to foo.foo-x.foo1. Also, the use of for loop will eliminate the files that do not end in .foo.
    – unxnut
    Aug 10 '18 at 21:08
  • I took your loop into account. It would not process a file called foo.foo-x. My example in my comment does end with .foo though.
    – Kusalananda
    Aug 10 '18 at 21:12
  • OP said "I'd like to rename all the files in the current directory, that have "foo" for the extension, to the same name but with foo1 for the extension."
    – unxnut
    Aug 10 '18 at 21:19

Adding a 1 to the name of all files whose name originally end with .foo:

find . -type f -name '*.foo' -exec mv -i {} {}1 ';'

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.