0

I have a folder with files

a1.cpp
a2.cpp
a3.cpp
a4.cpp
a5.cpp
a6.cpp

I wish to change extension of files ending in the range 2 to 5 to .java

How do I rename those files without using a loop and with the help of xargs?

the final output would be

a1.cpp
a2.java
a3.java
a4.java
a5.java
a6.cpp

1 Answers1

5

As always when using xargs with filenames, you must be careful if your filenames contain non-trivial characters.

That said, and assuming you have the GNU version of find and xargs with the -print0 and -0 options, the following will do:

find . -type f -name 'a[2-5].cpp' -print0 | xargs -0 rename 's/cpp$/java/'

This will use find to generate the list of relevant files according to your requirement, and output them as NULL-terminated string to ensure that filenames with spaces etc. are correctly handled. Then, xargs with the corresponding -0 option is used to invoke the (external) rename tool to which you can supply a sed style name transformation command (note that this assumes the Perl-based rename tool, not the util-linux variant, as noted by @ilkkachu - see here for a discussion).

I don't know if that can be called an "efficient way" to use xargs, but from your comment I take it that you want to explore xargs possibilities, and this is a reasonably reliable way to do it. The task you describe can be done entirely without xargs using exactly that rename command by using shell syntax features, as in:

rename 's/cpp$/java/' a[2-5].cpp

If you don't have the Perl version of rename, but the util-linux variant, the corresponding command would be

rename ".cpp" ".java" a[2-5].cpp

However, for lack of RegEx-Style anchors this will replace the first occurence of the original pattern with the substitution. In this case, where the task is to change the file suffix, this is unlikely to be a problem because .cpp will only occur once, at the end of the name, but in the general case you have to be careful when formulating the command.

AdminBee
  • 22,803
  • Thank @AdminBee. It worked – Sam Mend Sep 14 '21 at 14:42
  • @SamMend You're welcome. I added it to the answer. If you found the answer useful, please consider accepting it so that others facing a similar issue may find it more easily. – AdminBee Sep 14 '21 at 14:46
  • @AdminBee Another find/xargs hint: If you're going to xargs something risky (mv, rm, apt uninstall, ... ) stick an echo in front of your command and look at the command you're generating. – waltinator Sep 14 '21 at 17:17
  • +1. Also, perl rename can take a list of filenames on stdin (with \n as the default separator, or NUL with -0), so xargs is redundant. find ... -print0 | rename -0 's/cpp$/java/' – cas Sep 14 '21 at 22:38