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.
-
1Why do you think there will be an easy way without perl or regex?Falmarri– Falmarri2010年10月19日 17:58:45 +00:00Commented Oct 19, 2010 at 17:58
-
I don't know, maybe im wrong. Why doesn't the attempted script work?? plz...Vass– Vass2010年10月19日 18:21:22 +00:00Commented Oct 19, 2010 at 18:21
3 Answers 3
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 variablevar
with theword
prefix (if any) removed;${var%word}
remove shortest suffix: the value of variablevar
with theword
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.
-
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 directoryVass– Vass2010年10月19日 16:32:36 +00:00Commented 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 wordsMeasurements
,Panama
, etc. and thus makemv
think that you want to move filesMeasuremens
,Panama
, etc. into a singleMeasurementsPanama...
which must then be a directory. Usefor f in *.xml; do mv "$f" "${f//[ -]/}"; done
instead. (See Gilles' answer as well.)Riccardo Murri– Riccardo Murri2010年10月19日 21:37:27 +00:00Commented Oct 19, 2010 at 21:37
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//[- ]/}'
-
thanks alot. perl is a bit beyond me as well as zsh, but the other part is great.Vass– Vass2010年10月19日 22:57:22 +00:00Commented Oct 19, 2010 at 22:57
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
-
1Backticks 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
user unknown– user unknown2011年02月10日 09:31:20 +00:00Commented Feb 10, 2011 at 9:31