6

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?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
user2021539
  • 949
  • 3
  • 14
  • 31
  • this one: http://stackoverflow.com/questions/2709458/bash-script-to-replace-spaces-in-file-names – jsedano Apr 04 '13 at 00:10
  • As was suggested in a comment to one of your other, related questions, get the quotes out of the variable content. Otherwise the shell will look for a file with " in its name. – tink Apr 04 '13 at 00:11
  • I've got with and without the quotes. Please read above. "Currently, $1 and $2 have hardcoded quotes at the beginning and end. $onam and $dnam are the equivalents without the hardcoded quotes." – user2021539 Apr 04 '13 at 00:26

1 Answers1

6

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
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • mv "$onam" "$dnam" mv: cannot move `/home/bryan/renametest/TestFolder' to a subdirectory of itself, `/home/bryan/renametest/TestFolder/test---file' – user2021539 Apr 04 '13 at 00:32
  • $onam=/home/bryan/renametest/TestFolder/test file – user2021539 Apr 04 '13 at 00:35
  • That's a separate problem. You are apparently trying to move a folder into a new location, and that new location is a subdirectory of its current location. The error message you show is inconsistent with the claimed value of `$onam`. Show the output of `sh -x yourscript`, along with any regiments you provide, in an update to your question (so you can format the output properly). – Jonathan Leffler Apr 04 '13 at 00:40
  • No. If you check the value of onam, you will see that the mv command is breaking the value because of the spaces between "test" and "file". I've given the exact value of onam above. 1 is equivalent to onam, but with hardcoded quotes. – user2021539 Apr 04 '13 at 01:38
  • See the SSCCE. If you still have problems after studying it, then provide your own analogue of the SSCCE, and we can see where the differences are. – Jonathan Leffler Apr 04 '13 at 01:46
  • Thank you Jonathan. With your help I've got that part fixed. Now I have another that (I think) should be simple. – user2021539 Apr 04 '13 at 04:09
  • 1
    You can change the spaces to dashes without sed using bash variable replacement - `onam="the file"; echo ${onam// /-}` -> `the--file` – evil otto Apr 04 '13 at 04:13
  • 1
    @evilotto: yeah, but old habits die hard, and 25 years and more of old habits take a lot of killing. – Jonathan Leffler Apr 04 '13 at 04:22