basename with spaces in a bash script?

22,154

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.

Share:
22,154

Related videos on Youtube

cwd
Author by

cwd

Updated on July 11, 2020

Comments

  • cwd
    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
    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 find sed -i on systems that rely on bourne shell, or a 100 other gnu/linux-isms. Good luck to all. <End PetPeeveRant />
  • cwd
    cwd almost 13 years
    i 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
    Jens almost 13 years
    The 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 with for (( ... )), and the select construct.
  • Jens
    Jens over 12 years
    You're writing one pair of quotes and backslashes too much :-)
  • rjha94
    rjha94 over 12 years
    This does not work with bash shipped on my macosx lion (GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)
  • Jens
    Jens over 12 years
    @rjha94 What exactly does not work? What is the result? Please be very specific.
  • rjha94
    rjha94 over 12 years
    @jens my bad, I had forgotten "quotes" around the name
  • rjha94
    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
    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.