Vim Tips Wiki
(Change <tt> to <code>, perhaps also minor tweak.)
Tag: rollback
(12 intermediate revisions by 8 users not shown)
Line 1: Line 1:
  +
{{TipNew
{{TipProposed
 
|id=0
+
|id=1642
|previous=0
+
|previous=1641
|next=0
+
|next=1643
|created=December 22, 2009
+
|created=2009
 
|complexity=basic
 
|complexity=basic
 
|author=Whiteinge
 
|author=Whiteinge
Line 11: Line 11:
 
|category2=
 
|category2=
 
}}
 
}}
You can use Vim to quickly rename many files at once. This is essentially constructing an in-memory simplistic shell script.
+
You can use Vim to quickly rename many files at once. The steps are: create a list of files; change the list by constructing commands to rename each file; execute the commands. This is essentially an in-memory simplistic shell script.
   
  +
==Unix shell==
==Read in the list of files via stdin==
+
===Create list of files===
The backslash tells your shell to disregard any aliases for <tt>ls</tt>; we need plain output with no color.
 
  +
Starting at a shell prompt, you can send a list of file names to the standard input of Vim by entering:
 
<pre>
 
<pre>
 
\ls | vim -
 
\ls | vim -
 
</pre>
 
</pre>
   
 
The backslash tells your shell to disregard any aliases for <code>ls</code>; we need plain output with no color. Vim will open, displaying a list of file names.
==Make stand-alone shell commands==
 
In Vim you now have one filename per line. We need to construct each line to be a valid stand-alone shell command.
 
   
 
===Change to list of shell commands===
For example, to rename a bunch of files to lowercase:
 
 
In Vim you now have one file name per line. We need to change each line to be a valid stand-alone shell command.
  +
 
For example, to rename the files to lowercase:
 
<pre>
 
<pre>
 
:%s/.*/mv -i & \L&/g
 
:%s/.*/mv -i & \L&/g
 
</pre>
 
</pre>
   
To append <tt>.orig</tt> to each filename:
+
To append <code>.orig</code> to each file name:
 
<pre>
 
<pre>
 
:%s/.*/mv -i & &.orig/g
 
:%s/.*/mv -i & &.orig/g
 
</pre>
 
</pre>
   
To change all the <tt>.JPEG</tt> extensions to <tt>.jpg</tt>:
+
To change all <code>.JPEG</code> extensions to <code>.jpg</code>:
 
<pre>
 
<pre>
 
:%s/.*/mv -i & &/g
 
:%s/.*/mv -i & &/g
Line 44: Line 47:
 
</pre>
 
</pre>
   
  +
To substitute certain text in the filename:
You can use any Vim features here ([[VimTip398|macros]] are useful), as long as each line contains a valid shell command.
 
  +
<pre>
  +
:%s/.*/\="mv -i ".submatch(0)." ".substitute(submatch(0), "foo", "bar", "g")/g
  +
</pre>
   
  +
<code>\=</code> is substitute command expression. See [[VimTip755]] for more details.
==Commit your changes to disk==
 
  +
  +
Note: In case the file name contains space character, it should be surrounded with quotes.
  +
 
You can use any Vim features here ([[VimTip398|macros]] are useful), as long as each line results in a valid shell command.
  +
  +
===Execute the commands===
 
<pre>
 
<pre>
 
:w !sh
 
:w !sh
 
</pre>
 
</pre>
   
The reason this works is Vim writes a file line-by-line. So if you have a list of 100 file names, it will execute 100 <tt>mv</tt> commands. Sure there are utilities out there that may do this better or more quickly, but Vim is always available and that's one less thing you have to remember.
+
The reason this works is Vim writes a file line-by-line. So if you started with a list of 100 file names, it will execute 100 <code>mv</code> commands. Sure there are utilities that may do this better, but Vim is always available and that's one less thing you have to remember.
   
  +
An alternative method of executing the commands is:
==Commit your changes to disk v2==
 
 
<pre>
 
<pre>
 
:%!bash
 
:%!bash
 
</pre>
 
</pre>
   
This will pipe the whole file to the system command <tt>bash</tt>, thus executing all of the move commands. This will also replace the file with the command's output, which is useful for commands besides mv. You can also visually select a small subset of lines, and only execute those commands:
+
This will pipe the whole buffer to the system command <code>bash</code>, thus executing all of the move commands. This will also replace the file with the command's output, which is useful for commands besides <code>mv</code>. You can also visually select a small subset of lines, and only execute those commands:
 
 
<pre>
 
<pre>
 
:'<,'>!bash
 
:'<,'>!bash
 
</pre>
 
</pre>
   
Again, this will replace the selected lines with the command's output. Useful for other commands.
+
Again, this will replace the selected lines with the command's output which can be useful for some commands.
  +
  +
==See also==
  +
*{{script|id=1721|text=renamer.vim}} plugin to list and rename files
   
 
==Comments==
 
==Comments==
 
{{todo}}
 
{{todo}}
 
*Probably should generalise by adding a section for Windows.
 
*Probably should generalise by adding a section for Windows.
 
====Changes====
 
*v2 submitted by jearsh
 

Revision as of 06:42, 13 July 2012

Tip 1642 Printable Monobook Previous Next

created 2009 · complexity basic · author Whiteinge · version 7.0


You can use Vim to quickly rename many files at once. The steps are: create a list of files; change the list by constructing commands to rename each file; execute the commands. This is essentially an in-memory simplistic shell script.

Unix shell

Create list of files

Starting at a shell prompt, you can send a list of file names to the standard input of Vim by entering:

\ls | vim -

The backslash tells your shell to disregard any aliases for ls; we need plain output with no color. Vim will open, displaying a list of file names.

Change to list of shell commands

In Vim you now have one file name per line. We need to change each line to be a valid stand-alone shell command.

For example, to rename the files to lowercase:

:%s/.*/mv -i & \L&/g

To append .orig to each file name:

:%s/.*/mv -i & &.orig/g

To change all .JPEG extensions to .jpg:

:%s/.*/mv -i & &/g
:%s/.JPEG$/.jpg/g

To remove duplicate extensions:

:%s/.*/mv -i & &/g
:%s/.jpg.jpg$/.jpg/g

To substitute certain text in the filename:

:%s/.*/\="mv -i ".submatch(0)." ".substitute(submatch(0), "foo", "bar", "g")/g

\= is substitute command expression. See VimTip755 for more details.

Note: In case the file name contains space character, it should be surrounded with quotes.

You can use any Vim features here (macros are useful), as long as each line results in a valid shell command.

Execute the commands

:w !sh

The reason this works is Vim writes a file line-by-line. So if you started with a list of 100 file names, it will execute 100 mv commands. Sure there are utilities that may do this better, but Vim is always available and that's one less thing you have to remember.

An alternative method of executing the commands is:

:%!bash

This will pipe the whole buffer to the system command bash, thus executing all of the move commands. This will also replace the file with the command's output, which is useful for commands besides mv. You can also visually select a small subset of lines, and only execute those commands:

:'<,'>!bash

Again, this will replace the selected lines with the command's output which can be useful for some commands.

See also

Comments

 TO DO 

  • Probably should generalise by adding a section for Windows.