basename with spaces in a bash script?
Solution 1
In the case where the assignment is a single command substitution you do not need to quote the command substitution. The shell does not perform word splitting for variable assignments.
MYBASENAME=$(basename "$1")
is all it takes. You should get into the habit of using $()
instead of backticks because $()
nests more easily (it's POSIX, btw., and all modern shells support it.)
PS: You should try to not write bash scripts. Try writing shell scripts. The difference being the absence of bashisms, zshisms, etc. Just like for C, portability is a desired feature of scripts, especially if it can be attained easily. Your script does not use any bashisms, so I'd write #!/bin/sh
instead. For the nit pickers: Yes, I know, old SunOS and Solaris /bin/sh
do not understand $()
but the /usr/xpg4/bin/sh
is a POSIX shell.
Solution 2
The problem is that $1
in
MYBASENAME="`basename $1`"
is not quoted. Use this instead:
MYBASENAME="$(basename "$1")"
Solution 3
You're missing one set of quotes!
MYBASENAME="`basename \"$1\"`"
That'll fix your problem.
Related videos on Youtube
cwd
Updated on July 11, 2020Comments
-
cwd almost 4 years
I'm working on a bash script to create a new folder in /tmp/ using the name of a file, and then copy the file inside that folder.
#!/bin/bash MYBASENAME="`basename $1`" mkdir "/tmp/$MYBASENAME" for ARG in "$@" do mv "$ARG" "/tmp/$MYBASENAME" done
Behavior:
When I type in
mymove "/home/me/downloads/my new file.zip"
it shows this:mkdir /tmp/my new file.zip mv: rename /home/me/downloads/my new file.zip to /tmp/my\nnew\nfile.zip:
I have lots of quotes around everything, so I don't understand why this is not working as expected.
Also, I have the form loop in there in case there are multiple files. I want them all to be copied to the same folder, based on the first argument's basename.
-
shellter almost 13 years+1 for using $() form of command substitution. Folks unless you're really, really sure that you'll be using a system that only has the bourne shell, why not upgrade your technology syntax to 1993 standards ;-) ! I bet you use
sed -i
without thinking about it. But you won't findsed -i
on systems that rely on bourne shell, or a 100 other gnu/linux-isms. Good luck to all. <End PetPeeveRant /> -
cwd almost 13 yearsi noticed a lot of the default shell scripts use sh instead of bash. i still can't tell too much of a difference, except with things like
echo \c
to keep a new line from appearing. thanks for the tips and helpful answer. -
Jens almost 13 yearsThe portable way with echo \c is to use
printf
where you just omit the\n
in the format string. The most often used bashisms arguably are the use of array variables, non-POSIX syntax like[[ ... ]]
for tests, for loops withfor (( ... ))
, and theselect
construct. -
Jens over 12 yearsYou're writing one pair of quotes and backslashes too much :-)
-
rjha94 over 12 yearsThis does not work with bash shipped on my macosx lion (GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)
-
Jens over 12 years@rjha94 What exactly does not work? What is the result? Please be very specific.
-
rjha94 over 12 years@jens my bad, I had forgotten "quotes" around the name
-
rjha94 over 12 years~/code/misc $ cat basename.sh #!/bin/sh MYBASENAME=$(basename "$1") ; echo $MYBASENAME ; ~/code/misc $ ./basename.sh "/usr/path with space/xyz" xyz
-
gongzhitaao about 10 years@Jens, I'm sorry about unintended downvoting. I meant to be upvoting. Could you edit your post a little bit so that I could undo my careless downvote. Sorry for the trouble.