28

I need to rename files names like this

transform.php?dappName=Test&transformer=YAML&v_id=XXXXX

to just this

XXXXX.txt

How can I do it?

I understand that i need more than one mv command because they are at least 25000 files.

Angelo Fuchs
  • 9,825
  • 1
  • 35
  • 72

11 Answers11

53

Easiest solution is to use "mmv"

You can write:

mmv "long_name*.txt" "short_#1.txt"

Where the "#1" is replaced by whatever is matched by the first wildcard. Similarly #2 is replaced by the second, etc.

So you do something like

mmv "index*_type*.txt" "t#2_i#1.txt"

To rename index1_type9.txt to t9_i1.txt

mmv is not standard in many Linux distributions but is easily found on the net.

nimrodm
  • 23,081
  • 7
  • 58
  • 59
19

If you are using zsh you can also do this:

autoload zmv
zmv 'transform.php?dappName=Test&transformer=YAML&v_id=(*)' '$1.txt'
d0k
  • 2,605
  • 19
  • 16
13

You write a fairly simple shell script in which the trickiest part is munging the name.

The outline of the script is easy (bash syntax here):

for i in 'transform.php?dappName=Test&transformer=YAML&v_id='*
do
    mv $i <modified name>
done

Modifying the name has many options. I think the easiest is probably an awk one-liner like

`echo $i  |  awk -F'=' '{print $4}'`

so...

for i in 'transform.php?dappName=Test&transformer=YAML&v_id='*
do
    mv $i `echo $i |  awk -F'=' '{print $4}'`.txt 
done

update

Okay, as pointed out below, this won't necessarily work for a large enough list of files; the * will overrun the command line length limit. So, then you use:

$ find . -name 'transform.php?dappName=Test&transformer=YAML&v_id=*' -prune -print |
while read
do
    mv $reply `echo $reply |  awk -F'=' '{print $4}'`.txt 
done
Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
  • there is a command for this called 'rename' in most linux distros. See briens answer. – 8jean Jan 08 '09 at 16:14
  • 2
    Maybe so, but not all UNIX systems (not on my Mac for example) *and* this is a general pattern that can be applied to other issues. – Charlie Martin Jan 10 '09 at 03:08
  • At least in Bash and Dash, a `for` loop over a glob (or any builtin, at that) is not subject to "command line too long" limitation, so your first approach would also work for a very long list of files; see [this answer](https://stackoverflow.com/a/33619281/3266847). – Benjamin W. Aug 13 '17 at 04:40
5

Try the rename command

Or you could pipe the results of an ls into a perl regex.

brien
  • 4,400
  • 4
  • 30
  • 32
  • And how exactly do you do that with the `rename` command along? – jfs Jan 06 '09 at 21:17
  • like this: rename transform.php\?dappName\=Test\&transformer\=YAML\&v_id\= '' transform.php* – 8jean Jan 08 '09 at 16:13
  • @8jean: As I understand the question the result should be: s/.*?v_id=(.*)/$1.txt/. I don't see that in your comment. – jfs Jan 08 '09 at 16:18
  • Ah, I missed the '.txt' extension. Seems like there's no easy way to add that using "rename". – 8jean Jan 09 '09 at 11:17
4

You may use whatever you want to transform the name (perl, sed, awk, etc.). I'll use a python one-liner:

for file in 'transform.php?dappName=Test&transformer=YAML&v_id='*; do 
    mv $file `echo $file | python -c "print raw_input().split('=')[-1]"`.txt;
done

Here's the same script entirely in Python:

import glob, os
PATTERN="transform.php?dappName=Test&transformer=YAML&v_id=*"

for filename in glob.iglob(PATTERN):
      newname = filename.split('=')[-1] + ".txt"
      print filename, '==>', newname
      os.rename(filename, newname)

Side note: you would have had an easier life saving the pages with the right name while grabbing them...

Federico A. Ramponi
  • 46,145
  • 29
  • 109
  • 133
  • Hah hah, my awk program is shorter. ;-) – Charlie Martin Jan 06 '09 at 20:37
  • Right :) awk is perfect for this kinds of jobs. Unfortunately, neither your sh script nor mine will work for 100000 files (there's a limit to a command line length, and the * may break such limit). If this is the case, rename or a dedicate script are better solutions. – Federico A. Ramponi Jan 06 '09 at 20:40
  • @Federico: I'd add that the Python script (`glob.iglob()`) has a better chance to work for 100000 files. – jfs Jan 06 '09 at 21:22
4
find -name '*v_id=*' | perl -lne'rename($_, qq($1.txt)) if /v_id=(\S+)/'
jfs
  • 399,953
  • 195
  • 994
  • 1,670
1

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.

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

thameera
  • 9,168
  • 9
  • 37
  • 38
  • You should point out that *you* wrote this tool, see https://meta.stackexchange.com/questions/94022/how-can-i-link-to-an-external-resource-in-a-community-friendly-way – Benjamin W. Aug 13 '17 at 04:30
0

I'd use ren-regexp, which is a Perl script that lets you mass-rename files very easily.

21:25:11 $ ls
transform.php?dappName=Test&transformer=YAML&v_id=12345

21:25:12 $ ren-regexp 's/transform.php.*v_id=(\d+)/$1.txt/' transform.php*

  transform.php?dappName=Test&transformer=YAML&v_id=12345
1 12345.txt


21:26:33 $ ls
12345.txt
Marc Abramowitz
  • 3,447
  • 3
  • 24
  • 30
-1

This should also work:

prfx='transform.php?dappName=Test&transformer=YAML&v_id='

ls $prfx* | sed s/$prfx// | xargs -Ipsx mv "$prfx"psx psx

-1

this renamer command would do it:

$ renamer --regex --find 'transform.php?dappName=Test&transformer=YAML&v_id=(\w+)' --replace '$1.txt' *
Lloyd
  • 8,204
  • 2
  • 38
  • 53
-10

Ok, you need to be able to run a windows binary for this.

But if you can run Total Commander, do this:

  1. Select all files with *, and hit ctrl-M

  2. In the Search field, paste "transform.php?dappName=Test&transformer=YAML&v_id="

    (Leave Replace empty)

  3. Press Start

It doesn't get much simpler than that. You can also rename using regular expressions via this dialog, and you see a realtime preview of how your files are going to be renamed.

Community
  • 1
  • 1
Wouter van Nifterick
  • 23,603
  • 7
  • 78
  • 122