Batch rename files

48,587

Solution 1

This should make it:

rename 's/^[0-9]*-//;' *

It gets from the beginning the block [0-9] (that is, numbers) many times, then the hyphen - and deletes it from the file name.


If rename is not in your machine, you can use a loop and mv:

mv "$f" "${f#[0-9]*-}"

Test

$ ls
23-aa  hello aaa23-aa
$ rename 's/^[0-9]*-//;' *
$ ls
aa  hello aaa23-aa

Or:

$ ls
23-a  aa23-a  hello
$ for f in *;
> do
>   mv "$f" "${f#[0-9]*-}"
> done
$ ls
a  aa23-a  hello

Solution 2

I think this command would better if you execute the command below:

ls * | sed -e 'p;s/old-name/new-name/' | xargs -n2 mv

Here
ls * - lists files in curent folder
sed -e - executes expression
p; - prints old file name
s/old-name/new-name/ - produce new filename
xargs -n2 - handles two arguments to mv
mv - gets two parameters and do move operation

Recommendation: before executing mv verify what you do is what you want to achieve with echo.

ls * | sed -e 'p;s/old-name/new-name/' | xargs -n2 echo

Following example renames

SCCF099_FG.gz5329223404623884757.tmp to
SCCF099_FG.gz

ls *tmp | sed -e 'p;s/\([0-9]\)\+\.tmp/ /g' | xargs -n2 echo
ls *tmp | sed -e 'p;s/\([0-9]\)\+\.tmp/ /g' | xargs -n2 mv

Solution 3

If the first numbers are always the same length:

for F in *new ; do
    mv $F ${F:8}
done

The ${parameter:number} does a substring expansion - takes the string starting at the 8th character.

There are many other string edits available in expansions to handle other cases.

Solution 4

Using renamer (Windows, Mac and Linux friendly):

$ renamer --find '/\d+-(.*)/' --replace '$1' *

This will strip all numbers and first hyphen from the start of all files in the current directory.

Solution 5

This might look a little complex, but it's pretty effective and works well on both *nix and OSX systems. It also acts recursively, renaming files in the current directory as well as any subdirectories:

find . -regex '.*/[0-9]\{7\}[-].*' -print > temp1 && \
cp temp1 temp2 && \
vi -c ":g/\([0-9]\{7\}[-]\)\(.*\)/s//\2/" -c ":x" temp2 && \
paste temp1 temp2 > temp3 && \
vi -c ":g/^/s//mv /" -c ":x" temp3 && \
sh ./temp3 && \
rm temp1 temp2 temp3

Here's a breakdown of what just happened:

The first line says to find (find) all files, starting with those in the current directory (.), whose name matches the pattern (-regex) of "7 numbers, followed by a dash, followed by 0 or more characters" ('.*/[0-9]\{7\}[-].*'), and write those file names and their respective paths (-print) to a file called temp1 (> temp1). Note that the -print directive is probably not necessary in most cases but it shouldn't hurt anything.

find . -regex '.*/[0-9]\{7\}[-].*' -print > temp1 && \

Then, copy (cp) the contents of temp1 to a file called temp2.

cp temp1 temp2 && \

Next, open the file temp2 using the vi text editor and give vi two commands (using -c to signify each new command):

  1. Command #1:
    • Search each line of temp2 (:g) for the same pattern we searched for above, except this time group the results using parentheses (\([0-9]\{7\}[-]\)\(.*\)).
    • For each matching line, move the cursor to where the match was found and replace the whole match with only the second group of the matched pattern (\2).
  2. Command #2:
    • Save the changes made to temp2 and close the file (:x).

The result of which being this:

 vi -c ":g/\([0-9]\{7\}[-]\)\(.*\)/s//\2/" -c ":x" temp2 && \

Now, concatenate the lines from temp1 with those of temp2 (paste) and write each newly combined line to a file called temp3 (> temp3).

paste temp1 temp2 > temp3 && \

Next, run vi again, doing the same steps as above except this time search for the beginning of each line (^) inside the file temp3 and add mv and one space right after it (mv).

vi -c ":g/^/s//mv /" -c ":x" temp3 && \

Then, execute the contents of temp3 (./temp3) as a shell script (sh).

sh ./temp3 && \

Finally, remove (rm) each of the temporary files we created during the whole process.

rm temp1 temp2 temp3
Share:
48,587
van
Author by

van

Updated on July 17, 2022

Comments

  • van
    van almost 2 years

    I want to batch re-name a number of files in a directory so that the preceding number and hypen are stripped from the file name.

    Old file name: 2904495-XXX_01_xxxx_20130730235001_00000000.NEW
    New file name:         XXX_01_xxxx_20130730235001_00000000.NEW
    

    How can I do this with a linux command?

  • Yossarian
    Yossarian over 10 years
    This doesn't work with my version of rename (util-linux-ng 2.17.2). What version are you using?
  • David Souther
    David Souther over 10 years
    rename is in util-linux on Fedora and Debian releases, but doesn't seem to be included by default on OSX.
  • fedorqui
    fedorqui over 10 years
    @Yossarian check my updated answer, using mv. Does it work to you?
  • Yossarian
    Yossarian over 10 years
    Yep, the mv command works for me. It seems there must be two versions of rename - mine requires three arguments (rename from to file).
  • mindsupport
    mindsupport almost 10 years
    Is it possible to install with dependencies ?
  • Lloyd
    Lloyd almost 10 years
    i'm not sure what you mean.. there are install instructions on the renamer site.. does that help?
  • mindsupport
    mindsupport almost 10 years
    node package manager seems having issues with package dependencies, so it didn't install just one command, and npm didn't install dependencies in auto mode.
  • Lloyd
    Lloyd almost 10 years
    i just ran npm install -g renamer - it installed correctly and works fine.. please ensure you have the latest node.js installed.. if you're still having problems, raise an issue here
  • Ryan
    Ryan about 8 years
    Super helpful. Thanks!
  • Luke Davis
    Luke Davis about 8 years
    I see this is old; but can you break down what's going on in this line? Here's my understanding: in the call to sed, if say there are 5 files present, the expression string prints each line and then prints its find-and-replaced copy immediately below; then, xargs parses this list of 10 items now 2-at-a-time, and passes them as arguments to mv. Is that right?
  • fedorqui
    fedorqui almost 8 years
    @cjungel not sure what you mean
  • Peter Nowee
    Peter Nowee over 6 years
    Slight variation I used for filenames containing spaces: find . -print0 | sed -z -e 'p;s/old-name/new-name/' | xargs -n2 -0 mv.