简体   繁体   中英

mv a file that contains spaces from a shell script

I am trying to mv a file (rename it to replace spaces with dashes). If I pass the source and dest arguments without quotes, the source is broken up because mv thinks it is the end of the argument.

If I surround source and dest with arguments, mv reports that the source can't be found. Currently, $1 and $2 have hardcoded quotes at the beginning and end. $onam and $dnam are the equivalents without the hardcoded quotes.

This command from a prompt works perfectly because source and dest are surrounded by quotes:

mv "/home/bryan/renametest/TestFolder/test file" "/home/bryan/renametest/TestFolder/test---file"

Here is what I've tried so far (inputs and results)

mv $1 $2
mv: cannot stat `"/home/bryan/renametest/TestFolder/test   file"'
   No such file or directory

mv $onam $dnam
mv: cannot move `/home/bryan/renametest/TestFolder' to a subdirectory of itself, 
  `/home/bryan/renametest/TestFolder/test---file'

mv $1 $dnam
mv: cannot stat `"/home/bryan/renametest/TestFolder/test   file"': 
  No such file or directory

mv $onam $2
mv: cannot move `/home/bryan/renametest/TestFolder' to `"/home/bryan/renametest/TestFolder/test---file"': 
  No such file or directory

How can I move those files with the spaces?

Use:

mv "$onam" "$dnam"

Basically, use quotes around variables that contain filenames that may contain spaces. However, the values should not themselves include quotes unless the filename or directory name contains quotes itself.

Unfortunately, I can't immediately think of an easy way to use the values like $1 with the quotes hard-coded around them. You'd have to mess with eval or thereabouts.


An SSCCE ( Short, Self-Contained, Correct Example )

This code is isomorphic with the code you showed, but actually does somewhat more. It is also safe to be run and cleans up behind itself. It assumes you are using bash . Note that the names with spaces contain more than one space in a row; it is quite easy to be fooled into a false sense of security if you experiment with names containing single spaces.

#!/bin/bash
testdir=test.$$
mkdir "$testdir" || exit 1

trap "rm -fr '$testdir'; exit 1" 0 1 2 3 13 15

(
    set -x
    x=$'\n\n'
    cd test.$$

    basedir="$PWD"
    sub1dir="rename  test"
    sub2dir="Test   Folder"
    subdir="$sub1dir/$sub2dir"

    mkdir -p "$basedir/$subdir"

    oldfile="test   file"

    cp /etc/group "$basedir/$subdir/$oldfile"

    echo "$x"
    ls -lR .

    echo "$x"
    newfile=$(echo "$oldfile" | sed 's/ /-/g')
    mv "$basedir/$subdir/$oldfile" "$basedir/$subdir/$newfile"
    ls -lR .

    echo "$x"
    new2dir=$(echo "$sub2dir" | sed 's/ /-/g')
    mv "$basedir/$subdir"  "$basedir/$sub1dir/$new2dir"
    ls -lR .

    echo "$x"
    new1dir=$(echo "$sub1dir" | sed 's/ /-/g')
    mv "$basedir/$sub1dir" "$basedir/$new1dir"
    ls -lR .
)

rm -fr "$testdir"
trap 0

#    $ mv "/home/bryan/renametest/TestFolder/test   file" "/home/bryan/renametest/TestFolder/test---file"
#
#Here are some inputs and results.
#
#    mv $1 $2
#    mv: cannot stat `"/home/bryan/renametest/TestFolder/test   file"': No such file or directory
#
#    mv $onam $dnam
#    mv: cannot move `/home/bryan/renametest/TestFolder' to a subdirectory of itself, `/home/bryan/renametest/TestFolder/test---file'
#
#    mv $1 $dnam
#    mv: cannot stat `"/home/bryan/renametest/TestFolder/test   file"': No such file or directory
#
#    mv $onam $2
#    mv: cannot move `/home/bryan/renametest/TestFolder' to `"/home/bryan/renametest/TestFolder/test---file"': No such file or directory
#
#Ideas?

You do have to be careful; note how I built up names from fragments and decomposed them etc. But with care, it can be done.

Example Output

Run with bash -x , but you could run it with just bash and you'd only skip a little of the output because it includes a set -x within the sub-shell code.

+ testdir=test.47648
+ mkdir test.47648
+ trap 'rm -fr '\''test.47648'\''; exit 1' 0 1 2 3 13 15
+ set -x
+ x='

'
+ cd test.47648
+ basedir=/Users/jleffler/tmp/soq/x3/test.47648
+ sub1dir='rename  test'
+ sub2dir='Test   Folder'
+ subdir='rename  test/Test   Folder'
+ mkdir -p '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test   Folder'
+ oldfile='test   file'
+ cp /etc/group '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test   Folder/test   file'
+ echo '

'



+ ls -lR .
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 rename  test

./rename  test:
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 Test   Folder

./rename  test/Test   Folder:
total 8
-rw-r--r--  1 jleffler  staff  2151 Apr  3 18:43 test   file
+ echo '

'



++ echo 'test   file'
++ sed 's/ /-/g'
+ newfile=test---file
+ mv '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test   Folder/test   file' '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test   Folder/test---file'
+ ls -lR .
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 rename  test

./rename  test:
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 Test   Folder

./rename  test/Test   Folder:
total 8
-rw-r--r--  1 jleffler  staff  2151 Apr  3 18:43 test---file
+ echo '

'



++ echo 'Test   Folder'
++ sed 's/ /-/g'
+ new2dir=Test---Folder
+ mv '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test   Folder' '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test---Folder'
+ ls -lR .
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 rename  test

./rename  test:
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 Test---Folder

./rename  test/Test---Folder:
total 8
-rw-r--r--  1 jleffler  staff  2151 Apr  3 18:43 test---file
+ echo '

'



++ echo 'rename  test'
++ sed 's/ /-/g'
+ new1dir=rename--test
+ mv '/Users/jleffler/tmp/soq/x3/test.47648/rename  test' /Users/jleffler/tmp/soq/x3/test.47648/rename--test
+ ls -lR .
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 rename--test

./rename--test:
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 Test---Folder

./rename--test/Test---Folder:
total 8
-rw-r--r--  1 jleffler  staff  2151 Apr  3 18:43 test---file
+ rm -fr test.47648
+ trap 0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM