Find the answer to your Linux question:
Results 1 to 5 of 5
I have th following bash script ( sfvsort ) that checks sfv files and moves directories if everything is ok: Code: # /bin/bash startingdir=$PWD if [ -d sfv_ok ] ; ...
  1. #1
    Linux User Daan's Avatar
    Join Date
    Aug 2005
    Location
    The Netherlands
    Posts
    320

    Question Bash newbie needs your help with spaces in dir names

    I have th following bash script (sfvsort) that checks sfv files and moves directories if everything is ok:

    Code:
    # /bin/bash
    
    startingdir=$PWD
    if [ -d sfv_ok ] ; then
    	echo 'sfv_ok exists.'
    else
    	mkdir sfv_ok
    	echo 'Made directory sfv_ok.'
    fi
    find $PWD -iname "*.sfv" | \
    while read I; do
    	cd "$(dirname "$I")"
    	cfv -i -f "$I" -q
    	testresult=$?
    	if [ $testresult = 0 ]; then
    		echo Command to issue: mv \"$(dirname "$I")\" \"$startingdir/sfv_ok/$(basename "$(dirname "$I")")\" 
    		mv \"$(dirname "$I")\" \"$startingdir/sfv_ok/$(basename "$(dirname "$I")")\"
    	fi	
    done
    When there are spaces in directory names it does not work:

    Code:
    daan@schmauck:~/dance$ ls
    Eskimo - Break Rules (2004)
    daan@schmauck:~/dance$ sfvsort
    Made directory sfv_ok.
    /home/daan/dance/Eskimo - Break Rules (2004)/00-eskimo-break_rules-cdr-2004-bmi.sfv: 1 files, 1 OK.  0.431 seconds, 28972.6K/s
    Command to issue: mv "/home/daan/dance/Eskimo - Break Rules (2004)" "/home/daan/dance/sfv_ok/Eskimo - Break Rules (2004)"
    mv: target `(2004)"' is not a directory
    daan@schmauck:~/dance$ mv "/home/daan/dance/Eskimo - Break Rules (2004)" "/home/daan/dance/sfv_ok/Eskimo - Break Rules (2004)"
    daan@schmauck:~/dance$ ls sfv_ok/
    Eskimo - Break Rules (2004)
    I'm puzzled for several reasons:

    1) Why doesn't it work? I've got the quotes.
    2) Why does it complain only after the fourth space and not after the second?
    3) Why does the mv command work when I copy paste it to the command line?

    How do I do it right?
    OS's I use: Debian testing, Debian stable, Ubuntu, Windows XP, Windows Vista

  2. #2
    Linux Newbie SagaciousKJB's Avatar
    Join Date
    Aug 2007
    Location
    Yakima, WA
    Posts
    162
    1. I have no idea why it doesn't work.
    2. Once again, can't help you
    3. My best guess is that "dirname" and "basename" aren't behaving consistently. When I tried to use them, I got quite a few weird results.

    How do you do it right? Well, okay, I tried this

    Code:
    #!/bin/bash
    
    startingdir=$PWD
    if [ -d sfv_ok ] ; then
            echo 'sfv_ok exists.'
    else
            mkdir sfv_ok
            echo 'Made directory sfv_ok.'
    fi
    find ./ -iname "*.sfv" | \
    while read I; do
            #cd "$(dirname "$I")" What is this for?
            echo cfv -i -f "$I" -q
            testresult=$?
            if [ $testresult = 0 ]; then
                    echo Command to issue: mv "$PWD/$(echo "$I" | sed "s/\.\///g")" "$startingdir/sfv_ok/$(echo "$I" | sed "s/\.\///g")"
                    mv "$PWD/$(echo "$I" | sed "s/\.\///g")" "$startingdir/sfv_ok/$(echo "$I" | sed "s/\.\///g")"
            fi
    done
    I'm not sure if this is satisfactory, however. Because, I'm not sure what you were planning with the cd command ( why would you cd to the cwd? ), or whether you're going to continue to execute from the cwd.

    So, basically what this does, it uses $PWD to print the parent working dir instead of dirname and basename ( they seemed to be really inconsistent ), and uses find to search "./" instead of $PWD to avoid applying the full file name to $I. We can then use sed to cut off the "./" part that is attached on by "find" to print the filename and $PWD.

    An even simpler solution.

    Code:
    #!/bin/bash
    
    startingdir=$PWD
    if [ -d sfv_ok ] ; then
            echo 'sfv_ok exists.'
    else
            mkdir sfv_ok
            echo 'Made directory sfv_ok.'
    fi
    find ./ -iname "*.sfv" | \
    while read I; do
            #cd "$(dirname "$I")" What is this for?
            echo cfv -i -f "$I" -q
            testresult=$?
            if [ $testresult = 0 ]; then
                    echo Command to issue: mv "$I" "./sfv_ok/$(echo "$I" | sed "s/\.\///g")"
                    mv "$I" "./sfv_ok/$(echo "$I" | sed "s/\.\///g")"
            fi
    done
    This simply uses "./" instead of including the full filename.


    Anyway, unfortunately I can't figure out why it wouldn't be working, or why it was working the way you had it.

    By the way, all of my testing wad done on a file named "The test From (200.sfv" to make circumstances similar to what you're dealing with.

  3. #3
    Trusted Penguin Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,230
    So the problem, at a glance, is with your escaping of quotes. In Bash, we quote so as to group arguments. When you escape them, you are saying "this is actually a quote". For instance:
    Code:
    mv "my file" new_dir
    In this example, mv sees its first argument as my file, and its second as new_dir.

    Code:
    mv \"my file\" new_dir
    In this example, mv sees its first argument as "my, its second as file", and its third as new_dir.

    In this line:
    Code:
    echo Command to issue: mv \"$(dirname "$I")\" \"$startingdir/sfv_ok/$(basename "$(dirname "$I")")\"
    the escaped quotes are correct, as we want them to appear in echo's output. In this line:
    Code:
    mv \"$(dirname "$I")\" \"$startingdir/sfv_ok/$(basename "$(dirname "$I")")\"
    The quotes should not be escaped, because we are actually using them to group arguments. Try this line instead:
    Code:
    mv "$(dirname "$I")" "$startingdir/sfv_ok/$(basename "$(dirname "$I")")"
    Hopefully, this answers questions 1).

    Question 3) is also easy: note that when you copied the line to run the mv command yourself, you did not escape the quotes. This is correct, and this is why the command worked.

    As for Question 2), this is actually due to the way that mv works. When you run this command:
    Code:
    mv \"/home/daan/dance/Eskimo - Break Rules (2004)\" \"/home/daan/dance/sfv_ok/Eskimo - Break Rules (2004)\"
    mv has a lot of arguments. They are:
    Code:
    "/home/daan/dance/Eskimo
    -
    Break
    Rules
    (2004)"
    "/home/daan/dance/sfv_ok/Eskimo
    -
    Break
    Rules
    (2004)"
    Without looking at the implementation, I can't say for certain, but I bet that the first thing that mv does is check that the destination (the last argument, in this case (2004)") is a valid directory. Because in this case, it obviously isn't, it throws an error before checking any of the other arguments.

    I hope that this makes sense!
    DISTRO=Arch
    Registered Linux User #388732

  4. #4
    Linux User Daan's Avatar
    Join Date
    Aug 2005
    Location
    The Netherlands
    Posts
    320

    Smile

    Thank you, SagaciousKJB and Cabhan! It's absolutely great that you've taken some time to look at my midnight hackings.

    Here's what your proposed corrections do:

    Code:
    daan@schmauck:~/dance$ ls
    Eskimo - Break Rules 2004
    daan@schmauck:~/dance$ sfvsortkjb1 
    Made directory sfv_ok.
    cfv -i -f ./Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv -q
    Command to issue: mv /home/daan/dance/Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv /home/daan/dance/sfv_ok/Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv
    mv: cannot move `/home/daan/dance/Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv' to `/home/daan/dance/sfv_ok/Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv': No such file or directory
    daan@schmauck:~/dance$ sfvsortkjb2 
    sfv_ok exists.
    cfv -i -f ./Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv -q
    Command to issue: mv ./Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv ./sfv_ok/Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv
    mv: cannot move `./Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv' to `./sfv_ok/Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv': No such file or directory
    daan@schmauck:~/dance$ sfvsortcab 
    sfv_ok exists.
    /home/daan/dance/Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv: 1 files, 1 OK.  0.022 seconds, 559279.8K/s
    Command to issue: mv "/home/daan/dance/Eskimo - Break Rules 2004" "/home/daan/dance/sfv_ok/Eskimo - Break Rules 2004"
    daan@schmauck:~/dance$ ls sfv_ok/
    Eskimo - Break Rules 2004
    daan@schmauck:~/dance$
    So Cabhan's improvement is correct. I'm not sure why I left the \ escapes, it makes a lot more sense like this.

    Why I cd into dirname before issuing the cfv command: here's what happens if I remove echo in line 13 in KJB's second script to activate the cfv command:

    Code:
    daan@schmauck:~/dance$ sfvsortkjb2.2 
    Made directory sfv_ok.
    01-eskimo_-break_rules-bmi.mp3 : No such file or directory
    ./Eskimo - Break Rules 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv: 1 files, 0 OK, 1 not found.  0.000 seconds, 0.0K/s
    daan@schmauck:~/dance$
    For some reason the name of mp3 to be checked is given without any indication of where it should be found:

    Code:
    daan@schmauck:~/dance$ cat Eskimo\ -\ Break\ Rules\ 2004/00-eskimo-break_rules-cdr-2004-bmi.sfv | grep mp3
    01-eskimo_-break_rules-bmi.mp3 30b22448
    daan@schmauck:~/dance$
    Thanks a million, guys!
    OS's I use: Debian testing, Debian stable, Ubuntu, Windows XP, Windows Vista

  5. #5
    scm
    scm is offline
    Linux Engineer
    Join Date
    Feb 2005
    Posts
    1,044
    As a general rule it's A Bad Idea (as you've already found out!) to put spaces in filenames since they're separators in proper operating systems. However, it has given you a valuable lesson in the proper use of quoting!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...