5

I have a directory of files,

Measurements Panama 2009年03月22日 Session1.xml
Measurements Panama 2009年03月22日 Session2.xml
Measurements Panama 2009年03月22日 Session3.xml
Measurements Panama 2009年03月22日 Session4.xml
...
Measurements Panama 2009年03月22日 Session10.xml

and I want to remove the blank spaces and the - dash characters. I don't want to use the rename command because I don't know perl or regular expressions. From another post a recommendation for removing part of a file name was:

for f in *.png; do mv $f ${f#image}; done

this looks nice. I can't figure out what the # character does (I assume it removes the string "image" from the file names?), anyways -- how do I remove the spaces and dashes?

I get an error that the files are not a directory when doing

[jings]s0128943: for f in *.xml; do mv $f ${f//[ -]/};done
mv: target `MeasurementsPanama20090322Session10.xml' is not a directory
mv: target `MeasurementsPanama20090322Session1.xml' is not a directory

etc for all the files.

Jeff Schaller
68.8k35 gold badges122 silver badges263 bronze badges
asked Oct 19, 2010 at 15:50
2
  • 1
    Why do you think there will be an easy way without perl or regex? Commented Oct 19, 2010 at 17:58
  • I don't know, maybe im wrong. Why doesn't the attempted script work?? plz... Commented Oct 19, 2010 at 18:21

3 Answers 3

6

You can find information the ${...} substitutions in your shell's man page, for example bash(1). The most common:

  • ${var#word} remove shortest prefix: the value of variable var with the word prefix (if any) removed;

  • ${var%word} remove shortest suffix: the value of variable var with the word suffix removed (if any).

  • ${var/pattern/replacement} remove first occurrence of pattern

  • ${var//pattern/replacment} remove all occurrences of pattern

So, in your example ${f#image} expands to the value of f (e.g., image01.png) removing the image prefix, so it yields the value 01.png.

The word and replacement part in the ${...} expansions are subject to the same wildcard expansions as filenames; therefore, if you want to remove spaces and -, you could use ${f//[ -]/} (replaces any occurrence of characters and - with a null string.

All details on the man page.

answered Oct 19, 2010 at 16:00
2
  • I get an error that the files are not a directory[jings]s0128943: for f in *.xml; do mv $f ${f//[ -]/};done mv: target MeasurementsPanama20090322Session10.xml' is not a directory mv: target MeasurementsPanama20090322Session1.xml' is not a directory Commented Oct 19, 2010 at 16:32
  • 2
    @Vass Since your file names contain spaces you need to quote them, otherwise the shell will expand $f to separate words Measurements, Panama, etc. and thus make mv think that you want to move files Measuremens, Panama, etc. into a singleMeasurementsPanama... which must then be a directory. Use for f in *.xml; do mv "$f" "${f//[ -]/}"; done instead. (See Gilles' answer as well.) Commented Oct 19, 2010 at 21:37
2

If you have the perl rename (e.g. because you're on Debian or Ubuntu), it is the simplest way of skinning this particular cat (as in an individual cat — there are plenty of tools for mass renaming, and searching the archives of this site and Super User should find all the major ones).

rename 's/[- ]//g' *.xml

That being said, your script would have worked if you had followed the most important shell programming principle: all variable substitutions must be double-quoted. (Why do you need this extra bit of syntax fluff? Because there are cases where you actually want the unquoted behavior. But these cases are rather rare.)

for f in *.xml; do mv "$f" "${f//[ -]/}"; done

With zsh, you wouldn't need to write a loop: you could use the convenient zmv function.

autoload zmv
zmv '(*.xml)' '${1//[- ]/}'
answered Oct 19, 2010 at 20:14
1
  • thanks alot. perl is a bit beyond me as well as zsh, but the other part is great. Commented Oct 19, 2010 at 22:57
1

You might also use sed to build the new name. There it would be

for i in *.xml; do mv "$i" `echo "$i" | sed -e "s/[ -]//g"`; done
answered Oct 19, 2010 at 16:14
1
  • 1
    Backticks are deprecated. Recommendet is $(...) instead, which is easy to nest, and not so easy to be overseen or confused with apostrophs: for i in *.xml; do mv "$i" $(echo "$i" | sed -e "s/[ -]//g"); done Commented Feb 10, 2011 at 9:31

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.