mv command not working as expected

I have a need to replace spaces with underbars in all the directory tree from a certain sub-directory. The files were copied on an external drive from a family member that uses Windows.  I prefer to use *nix things, so for Windows I use Cygwin.  

Given that I have a testing file "My Family" in the current working directory, issuing the following command does the expected:

mv -T "My Family" My_Family

I want to use find to sweep all the files and directories from my starting directory, and pass each file/directory name to a script that does the same thing, but allows for the passing of arguments -- So the entire script (called sp2underbar) is:

#!/bin/bash
targ=`echo $1 | tr ' ' '_'`
/usr/bin/mv -T \'$1\' $targ              

The execution of the script gives this:

$ sp2underbar  "My Family"
/usr/bin/mv: extra operand `My_Family'
Try `/usr/bin/mv --help' for more information.

If I substitute for the variables as they would appear in the script and run the result manually on the command line, the rename works as expected.

I tried the same test exercise on an actual Linux box with the same results, so please don't advise that there is "something wrong with Cygwin"....

So what else is it? What am I missing?
Kimberly_BAsked:
Who is Participating?
 
ozoCommented:
/usr/bin/mv -T "$1" $targ
0
 
Frosty555Commented:
Your escaped single quotes are not having the desired effect, and the "My Family" subdirectory is being treated as two distinct parameters by the mv command ("My", and "Family").

Try replacing the single quotes with doublequotes:

#!/bin/bash
targ=`echo $1 | tr ' ' '_'`
mv -T "$1" "$targ"

Open in new window


You can set up the script to allow extra arguments to pass to mv through some clever use of parameter shifting like so:

#!/bin/bash
src="$1"
targ=`echo $1 | tr ' ' '_'`
shift
echo $targ;
mv -T $@ "$src" "$targ"

Open in new window

0
 
Kimberly_BAuthor Commented:
Changing single to double quotes had no effect on the outcome.  If the source is a file then the target is to be a file (not a directory) and if the source is a directory, then the target is to be a directory as well.  In this example "My Family" is a file.  I am using the -T flag.

I don't see what benefit `shift` has in this discussion, but maybe I'm just dense.  The only reason for the script was to simplify passing the source name in as the only argument, and using that to calculate the target name. Script would likely run from a `find` command... like this:

# Pass each file name to the script, script renames based on the argument passed in
find . -type f -exec sp2underbar "{}" \;    

# Same for directories, in a subsequent pass
find . -type d -exec sp2underbar "{}" \;
0
 
Kimberly_BAuthor Commented:
Yep, tried to get too fancy -- didn't need to escape the quotes in this case -- originally was trying to run this as a one-liner and do the substitute for space directly on the "find" command line (where escapes were needed), then brought that thinking into the script when I decided to go that route.   KISS principle applies.  Thanks!
0
 
mikelfritzCommented:
One more way:

find .  | while read targ;
do
target=`echo "$targ" | sed 's/ /_/g'`;
mv "$file" "$target";
done;


You would have to run this over and over until it traverses the structure since it changes from the root up and files in higher dirs wouldn't be found since the parent name changed.  Could be wrapped in a while loop I guess.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.