问题
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?
回答1:
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
来源:https://stackoverflow.com/questions/15800389/mv-a-file-that-contains-spaces-from-a-shell-script