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?

3
  • this one: stackoverflow.com/questions/2709458/… Commented Apr 4, 2013 at 0: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. Commented Apr 4, 2013 at 0: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." Commented Apr 4, 2013 at 0:26

1 Answer 1

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 
Sign up to request clarification or add additional context in comments.

8 Comments

mv "$onam" "$dnam" mv: cannot move /home/bryan/renametest/TestFolder' to a subdirectory of itself, /home/bryan/renametest/TestFolder/test---file'
$onam=/home/bryan/renametest/TestFolder/test file
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).
You can change the spaces to dashes without sed using bash variable replacement - onam="the file"; echo ${onam// /-} -> the--file
@evilotto: yeah, but old habits die hard, and 25 years and more of old habits take a lot of killing.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.