?

Log in

No account? Create an account

Renaming files with whitespace in their names

« previous entry | next entry »
Jul. 16th, 2013 | 08:04 pm

Is there a good way of programmatically renaming files with whitespace in their names on the shell, without resorting to e.g. Perl? Suppose that you have files with names like these:

foo bar.ext@extrafluff
lorem ipsum.ext@randomfluff

(wget likes to produce these, BTW, in case you're wondering.) Now you want to remove the extra fluff. My first instinct on the shell is to use basename(1); for files without whitespace in their names, this would be easy enough:

$ for i in *.ext@extrafluff ; do mv $i `basename $i @extrafluff` ; done

But since there is whitespace, you have to double-quote the filenames, and then the problems start:

$ for i in *.ext@extrafluff ; do mv "$i" `basename "$i" @extrafluff` ; done

This isn't enough; you'd also have to quote the second argument to mv(1), but there seems to be no altogether straightforward way of doing this. Now my shell-fu is decidedly rudimentary (and even that's giving it too much credit), so I just immediately switch to Perl and do something like this:

#!/usr/bin/perl

@files = <*.ext@extrafluff>;

foreach(@files) {
    ($new = $_) =~ s/\@extrafluff$//;
    rename $_, $new;
}

This works like a charm, but nonetheless, I'm wondering — suppose you didn't have Perl available, how would you do it using just the shell's own tools? (And I don't mean using sed(1) and friends to automatically slap together a script containing all the right mv(1) commands or so; I'm looking for pure solutions. :P)

EDIT: see the comments for an elegant shell-only solution.

EDIT, 2015-01-03: relatedly, for renaming e.g. files named "Verbose extra fluff FILE_001.BIN" etc. to "FILE_001x.BIN", you can also use the following:

#!/usr/bin/perl
$ for i in Verbose* ; do mv "$i" `basename "$i" .BIN | sed 's/Verbose extra fluff //'`x.BIN ; done
Tags: ,

Link | Leave a comment | Share

Comments {4}

(Deleted comment)

Schneelocke

(no subject)

from: schnee
date: Jul. 16th, 2013 07:51 pm (UTC)
Link

Hmm, I don't seem to have rename. I'll have to see if there's a package for that, though; it seems useful.

Ah, and I didn't know bash did that! Thanks, that should come in handy. :)

Edited at 2014-01-11 11:15 pm (UTC)

Reply | Parent | Thread

Morton Fox

(no subject)

from: mortonfox
date: Jul. 18th, 2013 06:30 pm (UTC)
Link

Nesting backticks within double quotes actually seems to do the trick in my copy of bash:

for i in *.ext@extrafluff; do mv "$i" "`basename "$i" @extrafluff`"; done


Failing that, breaking it up into multiple statements may work too:

for i in *.ext@extrafluff; do j=`basename "$i" @extrafluff`; mv "$i" "$j"; done

Reply | Thread

Schneelocke

(no subject)

from: schnee
date: Jul. 18th, 2013 06:37 pm (UTC)
Link

for i in *.ext@extrafluff; do mv "$i" "`basename "$i" @extrafluff`"; done

Hmm, I'm fairly sure I tried that and found it didn't work — I assumed it was due to the nested double-quotes.

for i in *.ext@extrafluff; do j=`basename "$i" @extrafluff`; mv "$i" "$j"; done

Ah, yes, good idea. :) Thanks!

Edited at 2013-07-18 06:37 pm (UTC)

Reply | Parent | Thread