Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

basename with spaces in a bash script?

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.

like image 954
cwd Avatar asked Aug 25 '11 16:08

cwd


People also ask

How do you handle spaces in bash?

Filename with Spaces in Bash A simple method will be to rename the file that you are trying to access and remove spaces. Some other methods are using single or double quotations on the file name with spaces or using escape (\) symbol right before the space.

Do spaces matter in bash?

It doesn't matter much whether how many space you indent, though most people seem to use 4 spaces or 8. Just make sure that your do's and done's line up and you'll be fine.

What does basename mean in shell script?

basename takes a filename and prints the last component of the filename. Optionally, it can also remove any trailing suffix. It is a simple command that accepts only a few options. The most basic example is to print the file name with the leading directories removed: basename /etc/passwd.

What does basename mean in bash?

In Linux, the basename command prints the last element of a file path. This is especially useful in bash scripts where the file name needs to be extracted from a long file line. The “basename” takes a filename and prints the filename's last portion. It can also delete any following suffix if needed.


3 Answers

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.

like image 117
Jens Avatar answered Oct 16 '22 22:10

Jens


The problem is that $1 in

MYBASENAME="`basename $1`" 

is not quoted. Use this instead:

MYBASENAME="$(basename "$1")"
like image 6
Ulrich Dangel Avatar answered Oct 16 '22 22:10

Ulrich Dangel


You're missing one set of quotes!

MYBASENAME="`basename \"$1\"`"

That'll fix your problem.

like image 3
Carl Norum Avatar answered Oct 16 '22 21:10

Carl Norum