Batch rename files

2019-01-22 04:10发布

问题:

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?

回答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


回答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


回答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.



回答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.



回答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


回答6:

There is also a handy GUI tool pyRenamer https://wiki.ubuntuusers.de/pyRenamer/



回答7:

vimv lets you rename multiple files using Vim's text editing capabilities.

Entering vimv opens a Vim window which lists down all files and you can do pattern matching, visual select, etc to edit the names. After you exit Vim, the files will be renamed.

The screencast in the README file shows how it solves original poster's question.

[Disclaimer: I'm the author of the tool]



回答8:

You can use this tool: rnm

Code to do what you want:

rnm /path/to/the/directory -fo -dp -1 -rs '/^\d+-//' -ss '^\d+-'

-fo is for file only mode
-dp is the depth of directory ( -1 means unlimited depth).
-rs is replace string. \d+- regex is being replaced with empty string.
-ss is search string, it searches for files with ^\d+- regex. (It could be omitted though, some harmless error messages would be printed on screen).



回答9:

I really like something as "rename *.mp3 *.mp4".

But none of other answers give me that. So I wrote a haskell program to do it.

https://hackage.haskell.org/package/batch-rename

With this you can do: batch_rename "DCIM*.jpg" "*.png"