Hello, On Mon, 01 Dec 2008, David C. Rankin wrote:
Bash wizards:
I have run across another quandary. I am trying to get a filespec from the command line like:
./scriptname file1*
and file name expansion occurs before I can assign the filespec to a variable.
You can't. But (see below).
I want to be able to grab the 'file1*' filespec without having to require that it be enclosed in single quotes (./scriptname 'file1*').
You MUST use single or double quotes around the pattern or escape the wildcard characters, if you want to pass the pattern to your script. I.e. one of: ./script 'file1*' ./script "file1*" ./script file1\*
I'm using the filespec like:
FILESPEC=$1
*BLAM* Missing double quotes.
NEWNAME=$2
*BLAM* Missing double quotes.
for i in $(ls ${FILESPEC}); do
*BLAM* Not missing quotes, but it'll bite you _badly_ anyway, for any filename containg special characters (like whitespace and a bunch of others). DO NOT EVER USE THAT.
echo -n "moving $i --> ${NEWNAME}.${i##*.}"
ok.
if mv $i ${NEWNAME}.${i##*.}; then
*BLAM* Missing double quotes. Twice! [..]
Can I do it, or do I have to look at handling the expanded command line in another way like an array or something?
Why would you want this? You would just pass the pattern back to the (sub-)shell (and on to ls, which'll bite you anyway) and then the shell has to expand it anyway.
The easiest way would probably be to swap NEWNAME to $1 and then do $2 until I run out of parameters, but that would defeat my preference of the command line being ./rename what to-what. What is the best way to skin this cat? (I've also learned that the expression can be 'wash that pig' in some parts as well)
The easiest way is: mmv 'file1*' 'newname#1' (with '-v' if you like) or use krename. But generally for "looping over files", you can do something like: ==== UNTESTED! ==== #!/bin/bash newname="$1"; ## get base for target filename, as first argument shift; ## get rid of it (pop it from the argument list) ## loop over the remaining arguments, i.e. the file list, possibly ## generated by the shell from the pattern for name; do ## == implicit: for name in "$@"; do ## let the shell and/or find + xargs ## take care of what names you get to ## see. target="${newname}.${name##*.}" mv -i "$name" "$target" ## do NOT use such a 'mv' in a script ## without -i, EVER! Unless you ## implement a check for and handle an ## existing target yourself (which is ## why I use 'target' here at all), or ## you like to shoot yourself in the ## foot with a bazooka and lose data. done ==== Call it as: ./script newname pattern* If you want verbose output, just use 'mv -i -v ...'. BTW: you realize, that you'll get collisions for any 2 files matched by the pattern, which have the same extension (after the last '.')? To remedy this, you'll have to construct "target" differently. Also, you could implement verbosity and target (newname) as options, but that (parsing options) is a bit out of scope right now. Any questions? HTH, -dnh PS: sorry if I sound a bit harsh ... -- If ignorance is bliss, why aren't there more happy people? -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org