Vim Tips Wiki
(Added UNIX equivalent, mention UnxUtils for Windows)
(Corrected external link syntax (still getting to know this wiki...))
Line 148: Line 148:
   
 
==Comments==
 
==Comments==
I sometimes use this trick on UNIX, where it's as simple as <code>find /some/directory | vim -</code>. Which brings me to the following idea: The <code>find</code> program is included in [[http://unxutils.sourceforge.net/ UnxUtils]] which means the same trick should work fine on Windows once you've installed UnxUtils.
+
I sometimes use this trick on UNIX, where it's as simple as <code>find /some/directory | vim -</code>. Which brings me to the following idea: The <code>find</code> program is included in [http://unxutils.sourceforge.net/ UnxUtils] which means the same trick should work fine on Windows once you've installed UnxUtils.

Revision as of 15:54, 31 August 2010

Occasionally I use Vim to search for filenames in a directory listing rather than relying on windows search or some other search tool that might not be available at the time. This has the advantage of allowing me to use vim commands to filter and modify the results as needed. The main drawback with this approach is that dos directory listings don't list the filename and path on a single line thus requiring more advanced searches to be constructed to find anything. The following commands will take a dos directory listing created with dir /s and turn it into a line by line listing containing the full path to each file or directory. Note: This entry is of primary relevance to windows/dos users but the ideas outlined might be useful to users of other systems.

Desired Result

Turn this:

 Directory of C:\WINNT

20/08/2010  09:31 AM    <DIR>          .
20/08/2010  09:31 AM    <DIR>          ..
30/08/2010  09:13 AM                 0 0.log
29/12/2006  12:31 AM            19,569 003199_.tmp
03/06/2008  07:04 PM    <DIR>          addins
30/07/2010  08:43 PM    <DIR>          AppPatch
04/08/2004  10:00 PM             1,272 Blue Lace 16.bmp
24/02/2009  03:28 PM    <DIR>          bruce lee!
04/08/2004  10:00 PM            82,944 clock.avi
30/07/2010  08:16 PM               373 cmsetacl.log
04/08/2004  10:00 PM            17,062 Coffee Bean.bmp
19/08/2010  09:17 PM           324,805 comsetup.log

into this:

C:\WINNT\
C:\WINNT\0.log
C:\WINNT\003199_.tmp
C:\WINNT\Blue Lace 16.bmp
C:\WINNT\clock.avi
C:\WINNT\cmsetacl.log
C:\WINNT\Coffee Bean.bmp
C:\WINNT\comsetup.log
C:\WINNT\addins\
C:\WINNT\AppPatch\
C:\WINNT\AppPatch\acadproc.dll
C:\WINNT\AppPatch\acgenral.dll
C:\WINNT\AppPatch\aclayers.dll

Getting the directory listing

To get a dos directory listing of your c drive try typing:

c:\>dir /s > dirlist.txt

to edit this listing in Vim:

vim dirlist.txt

now we can reformat the listing to be line based:

" remove blank lines
g/^\s*$/d

" remove header
g/^ Volume/d

" remove footer
g/^\s\+Total Files Listed/.,+2d

" remove directory entries
g/\s<DIR>\s/d

" replace file entries with filename followed by delimiter
%s/^\d\d\/\d\d\/\d\d\d\d  \d\d:\d\d [AP]M \s*[0-9,]\+ /``````::::::

" replace backslash path separators with forward slashes
%s/\\/\//g

" create a copy of the directory path and append /. One copy is left alone the other gets prepended to all files inside.
%s/^ Directory of \(.*\)\s*$/\1\/\r@@\1\/@@/

" join together files in a directory
g/^@@/,/File(s)/j

" remove folder info at end
%s/ [0-9,]\+ File(s)\s\+[0-9,]\+ bytes\s*$//

" prepend path to each file
%s/^@@\(.\{-}\)@@\(.*\)/\=substitute(submatch(2),"::::::",submatch(1),"g")/

" split into separate lines
%s/``````/\r/g

" remove blank lines
g/^\s*$/d

" convert forward slashes to backslashes
%s/\//\\/g

" remove blanks at line end
%s/\s*$

if you put this into a file and call it reformat.vim you can then source it on a directory listing using:

:so reformat.vim

Searching the result

now if you want to see only doc files you can do:

:v/\c\.doc$/d

or you want to show all the folders which contain .vim files:

:v/\c\.vim$/d
:%s/\c\\[^\\]\+\.vim$//
:sort u

Further Processing

To take this one step further we can now convert this filtered directory listing into a batch file to operate on each line.

Delete each file:

:%s/^\(.*\)/del "\1"/

Rename each file:

%s/^\(.*\)\\\([^\\]\+\)\.txt$/rename "\1\\\2.txt" "\1\\\2.txt.old"/

now save as a dos batch file

:w renamefiles.bat

and run.

Of course don't run this unless you are **absolutely sure** the commands do what you want. There are some edge cases that will cause the reformatting code to trip up if you have strange characters in your filenames.

References

Comments

I sometimes use this trick on UNIX, where it's as simple as find /some/directory | vim -. Which brings me to the following idea: The find program is included in UnxUtils which means the same trick should work fine on Windows once you've installed UnxUtils.