12

I have directory say /var/tmp/abc which has 4 files:

12345-ram-3e3r5-io9490-89adu9.csv
45434-dam-qwe35-to9490-43adu9.csv
11234-cam-yy3r5-ro9490-85adu9.csv
14423-sam-hh3r5-uo9490-869du9.csv

I want to rename all the CSV files (find all the files & rename them) in shortest possible (probably one-liner) way to this:

XXXXX-ram-3e3r5-io9490-89adu9.csv
XXXXX-dam-qwe35-to9490-43adu9.csv
XXXXX-cam-yy3r5-ro9490-85adu9.csv
XXXXX-sam-hh3r5-uo9490-869du9.csv
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
Rocky86
  • 651

4 Answers4

15

rename -n 's/(\w+)/XXXXX/' *.csv

remove the -n when happy.

SHawarden
  • 554
  • 2
    For a suitable version of rename. I assume this is Larry Wall's rename, from the rename package in Debian and derivative (and IIRC prename on systems of the RedHat persuasion). A very useful tool. – xenoid May 14 '19 at 07:01
  • 2
    perl-rename in arch linux – Lesmana May 14 '19 at 10:44
  • 1
    @SHawarden, I've tried to execute the command and read the relevant portion of man page to understand the replace pattern, but when adding the verbose flag, it outputs nothing and doesn't perform the file name changes, even though the current path has files with names similar to 12345_foo.csv. Do I have to perform any additional task to get it working (currently on Fedora 30)? It is a cleaner approach than looping. Thanks in advance! – dandev486 May 14 '19 at 11:23
  • 3
    @danieldeveloper001 Did you use rename or prename? See my comment above. man {the command} lists the authors at the end. – xenoid May 14 '19 at 11:39
  • 1
    @xenoid, didn't see your comment, sorry! I've used the packaged rename application, right now I'm on an Ubuntu machine, but I'll check the author and git a try to prename when I get access to a Fedora machine! I've made a quick research now based on your comment and apparently the packaged rename on RedHat based systems does not support match patterns, while the prename does. Thanks for the clarification! – dandev486 May 14 '19 at 12:29
  • 1
    If you are on Ubuntu then this is rename (which is a link to /usr/bin/file-rename, itself installed with the rename package). – xenoid May 14 '19 at 13:39
  • 1
    @xenoid, tested on my fedora machine, it was really a different package, you were correct! Thanks! :) – dandev486 May 15 '19 at 00:22
  • 2
    This only works on Debian-derived systems. Fedora-derived systems have a completely different rename command; see https://unix.stackexchange.com/a/238862/135943 – Wildcard May 15 '19 at 06:02
11

Try:

for f in *.csv; do mv -i -- "$f" "XXXXX-${f#*-}"; done

How it works:

  • for f in *.csv; do

    This starts a loop over all *.csv files.

  • mv -i -- "$f" "XXXXX-${f#*-}"

    This renames the files as you want, asking interactively before overwriting any file.

  • done

    This marks the end of the loop.

Example:

$ ls -1
11234-cam-yy3r5-ro9490-85adu9.csv
12345-ram-3e3r5-io9490-89adu9.csv
14423-sam-hh3r5-uo9490-869du9.csv
45434-dam-qwe35-to9490-43adu9.csv
$ for f in *.csv; do mv -i -- "$f" "XXXXX-${f#*-}"; done
$ ls -1
XXXXX-cam-yy3r5-ro9490-85adu9.csv
XXXXX-dam-qwe35-to9490-43adu9.csv
XXXXX-ram-3e3r5-io9490-89adu9.csv
XXXXX-sam-hh3r5-uo9490-869du9.csv
John1024
  • 74,655
4

I'm assuming that all your files starts with 5 numeric characters, so using the cut command to replace the initial numeric files by "XXXXX".

Below, the files before the command.

-rw-rw-r--. 1 daniel daniel 0 May 13 23:18 11111_bar_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 12345_baz_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 67890_foo_file.xml

Below, the one liner command.

for src in *.csv; do dst=XXXXX$(echo $src| cut -c6-); mv $src $dst; done;

Below, the files after the command.

-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 67890_foo_file.xml
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 XXXXX_bar_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 23:18 XXXXX_baz_file.csv

References:

Looping through command output in bash

Substrings in bash

dandev486
  • 219
  • 2
    Bash can do this sort of string manipulation, no need to fork a new process for each, please the other answer on how. – chx May 14 '19 at 23:45
  • 1
    @chx, already saw the other answers and acquired a little bit of knowledge from it, but thanks for pointing them out. Would you please elaborate on no need to fork a new process for each? – dandev486 May 15 '19 at 00:19
  • 3
    cut is a separate binary (/usr/bin/cut) and running it consumes more resources than using shell built ins. – chx May 15 '19 at 00:42
  • 2
    I see, it actually matters if the intent is renaming a lot of files. Thank you for the clarification! – dandev486 May 15 '19 at 00:55
1

no forks:

ls | perl -lne '$suf=substr($_,6); rename $_, "XXXXX-$suf"'

When you use a shell loop, the mv forks once per file. Perl's rename command does not.

(Perl's rename command has some restrictions, but in this specific case those restrictions don't apply.)

As for the rename command shown earlier, yes that works, but then you have all that confusion between two different kinds of rename and so on. If you have the right one, great, but if not, this works too.

If you don't have the perl-rename command and can't install it, you can just do this:

ls | perl -lne '$old=$_; s/(\w+)/XXXXX/; rename $old, $_'

As you can see, this uses the same substitution shown in the top answer. Of course the perl-rename has other bells and whistles (the top answer mentioned, -n already, then there's -0, -f, and so on), and the more of them you need, the more you should install that instead of rolling your own in this manner.

muru
  • 72,889
  • The usual implementations of a pipe will have forks. – muru May 17 '19 at 05:24
  • I meant, "won't fork once per file to be renamed", unlike even shell, where the "mv" forks /usr/bin/mv or whatever. This is because the "rename" command is a perl internal command that directly calls rename() in libc. Of course it has some restrictions, but in this specific example those restrictions don't apply. –  May 17 '19 at 05:31
  • 1
    That's also true of the rename command (top answer, also uses Perl), so maybe you should add a little more explanation than simply "no forks" to the answer. – muru May 17 '19 at 05:33