I have the misfortune of coming from a MS-DOS background – but at least it makes me appreciate how much more powerful Linux is. I've been working on getting my Linux-Fu up to par, but there are a couple things that could be done with DOS that I'm not sure how to accomplish most easily with Linux:
Renaming Multiple Files – Using Two Wildcards
c:\> dir
Directory of c:\
file1.txt
file2.txt
file3.txt
file4.txt
c:\>rename *.txt *.bak
c:\> dir
Directory of c:\
file1.bak
file2.bak
file3.bak
file4.bak
I know I could use find -exec
here but it it possible to use a shorter syntax – perhaps mv
with some special flags or syntax? I guess the key to this is the second *
wildcard as linux shouldn't have a problem with the first one (i.e. i know how to select the files i want to rename using wildcards)
Renaming a Single File – Using One Wildcard
c:\> dir
Directory of c:\
file1.txt
c:\>rename file1.txt *.bak
c:\> dir
Directory of c:\
file1.bak
This would be especially helpful when renaming long and unwieldy file names. I thought perhaps I could use mv file1.txt $1.bak
to end up with file1.txt.bak
which would also be acceptable but I'm not sure you can reference a the $1
parameter inline with a shell command. Again in this particular case it is just convenient of how ms-dos bastardizes the *
wildcard to be used as a sort of capture / replace match for part of the filename.
Filtering Directory Listings with a Wildcard
c:\> dir
Directory of c:\
file1.txt
file2.txt
file3.txt
file4.txt
text.txt
\temp (directory)
c:\> dir file*
Directory of c:\
file1.txt
file2.txt
file3.txt
file4.txt
c:\> t*
Directory of c:\
text.txt
\temp (directory)
I'm not sure what the right syntax for doing that with ls
is, or if it is even possible. If I did something like ls t*
it will recurse into directories starting with t
. My workaround has either been using find . --max-depth 1 -iname "t*"
or something like ls -al | grep t
– neither of which are as short and simple as dir t*
is.
Finally, I know I can set up aliases to make these long commands shorter, but I'd like to learn some out-of-the-box linux-fu for doing these things because sometimes you're connected to a remote system or working on a new machine.
So how can I mv
and ls
files the same way that I used to dir
and rename
files?
Best Answer
One of the fundamental differences between Windows
cmd
and POSIX shells is who is responsible for wildcard expansions. Shells do all the expansions required before starting the actual commands you asked for.cmd
mostly passes the wildcard patterns to the commands unmodified. (I say mostly, since I think there are exceptions, and environment variables are expanded under most circumstances.) This makes writing arename
that would work with the same syntax as incmd
quite tricky.But there is a
rename
for Linux - with completely different arguments, check out the man page (which is a bit terse on my system, andrename
comes from theutil-linux
package on my system, which should be widely available). Your first rename would be done like this:Note that the shell does the
*
expansion, sorename
itself actually thinks it was invoked like this:So you can guess the single file version:
If you don't want to use
rename
but implement this yourself, you could create a function for that. Assuming you only want to change the file extension, and for single-file rename, look at this:$newfile
is built using a substring removal to strip out the original extension, then concatenates the new extension. You can extend that function to handle multiple files relatively easily.As for your
ls
question, use the-d
switch. This will preventls
from listing the contents of directories.Demo:
Wildcard rename
Single-file rename
The default
ls
ls
that doesn't inspect directories