RabbieBurns Posted February 11, 2009 Posted February 11, 2009 Ive written a little bash script that sorts photos out of the sub folders and puts them all into the root folder, but my script doesnt seem to like folders with spaces. I think its the for loop, thinking the space means its a new item and it treats "Summer 2009" as Summer and 2009. Anyone point me in the right direction to sort this? cd /Photos/new #Move JPG files for directory in $(find . -type d) do (cd $directory for file in *.jpg do mv $file /Photos/new echo "Moved $file " done) done #Remove empty directorys find . -type d -exec rmdir {} \;
Gatt Posted February 11, 2009 Posted February 11, 2009 you need to escape them like so mkdir new\ folder This creates a directory called "new folder" Note the \ is right after word "new" so to cd into "Summer 2009" cd Summer\ 2009
Arcath Posted February 11, 2009 Posted February 11, 2009 try: chaning $directory on line 6 to ${directory/ /\\ } that should subsitute all the spaces in $directory to "\ " you will have to do it for file name aswell because "random picture.jpg" will be treated as "random" and "picture.jpg"
RabbieBurns Posted February 11, 2009 Author Posted February 11, 2009 you need to escape them like so mkdir new\ folder This creates a directory called "new folder" Note the \ is right after word "new" so to cd into "Summer 2009" cd Summer\ 2009 Thanks for the suggestion, but Im not making the folders, and also they arent being made via command line or on linux for that matter.
RabbieBurns Posted February 11, 2009 Author Posted February 11, 2009 try: chaning $directory on line 6 to ${directory/ /\\ } that should subsitute all the spaces in $directory to "\ " you will have to do it for file name aswell because "random picture.jpg" will be treated as "random" and "picture.jpg" I tried that, it didnt seem to work. Same error as before cd: 2009: No such file or directory mv: cannot stat `*.jpg': No such file or directory
powdarrmonkey Posted February 11, 2009 Posted February 11, 2009 Just wrap your variable in quotes: mv "$directory" Bash does greedy matching for variables AFAIK, but doesn't do regular expressions.
RabbieBurns Posted February 12, 2009 Author Posted February 12, 2009 I tried that before as well powdarmonkey thinking it would do the trick, but it didnt work either.
Arcath Posted February 12, 2009 Posted February 12, 2009 mv: cannot stat `*.jpg': No such file or directory That seems to imply that its taking "*" as a literal character, which athough isnt your current problem, might come up later
powdarrmonkey Posted February 12, 2009 Posted February 12, 2009 Ah, wait, I misread your question. Try this: for directory in $(find . -type d) do (cd $directory for file in `ls *.jpg` do mv $file /Photos/new .... This shells out to ls to get a list of .jpg files and works off that, instead of using the string literal '*.jpg'.
RabbieBurns Posted February 12, 2009 Author Posted February 12, 2009 (edited) Arcath the problem isnt with the *.jpg, as it works fine with non spaced directories The problem is the script cant change directory into a directory with a space, and therefore there are no jpg files for it to move, as the folder it tries to change into doesnt exist Edit: The folder name as is "Summer 2009" so the full error it gives is: cd: Summer: No such file or directory mv: cannot stat `*.jpg': No such file or directory cd: 2009: No such file or directory mv: cannot stat `*.jpg': No such file or directory (sorry should have posted the full error more clearly) Edited February 12, 2009 by RabbieBurns
powdarrmonkey Posted February 12, 2009 Posted February 12, 2009 You might also find this easier (note: untested) as I think all you're trying to do is find .jpg files in a tree, and move them all into one place. find . -name *.jpg -type f -print0 | xargs -0 mv '{}' /Photos/new One line to rule them all, one line to find them, one line to bring them all and in the darkness replace your whole script Your friends are 'man find' and 'man xargs'. 1
RabbieBurns Posted February 12, 2009 Author Posted February 12, 2009 You might also find this easier (note: untested) as I think all you're trying to do is find .jpg files in a tree, and move them all into one place. find . -name *.jpg -type f -print0 | xargs -0 mv '{}' /Photos/new One line to rule them all, one line to find them, one line to bring them all and in the darkness replace your whole script Your friends are 'man find' and 'man xargs'. "I think all you're trying to do is find .jpg files in a tree, and move them all into one place" <-- Yep thats exactly what Im attempting. Im not quite sure what this error means? roberts Photos # find . -name *.jpg -type f -print0 | xargs -0 mv '{}' /Photos/new mv: target `./new/Summer 2009/summer2.jpg' is not a directory
unixman Posted February 12, 2009 Posted February 12, 2009 I would do the obvious, which is to rename your directory to something like summer_2009.
RabbieBurns Posted February 12, 2009 Author Posted February 12, 2009 But if my script cant CD into a directory with a space, how will it recognize a directory with a space to change the space to _ ?
CyberNerd Posted February 12, 2009 Posted February 12, 2009 does this work? find . -type f -name "*.jpg" -exec mv {} ./new/path/ \;
RabbieBurns Posted February 12, 2009 Author Posted February 12, 2009 roberts Photos # find . -type f -name "*.jpg" -exec mv {} /tmp \; roberts Photos # ls /tmp 1.jpg 2.jpg holiday.jpg Yep. Thanks. So, does this mean that I cant use /Photos/new as the destination to move photos from /Photos/new/blah blah ?
powdarrmonkey Posted February 12, 2009 Posted February 12, 2009 (edited) Im not quite sure what this error means? roberts Photos # find . -name *.jpg -type f -print0 | xargs -0 mv '{}' /Photos/new mv: target `./new/Summer 2009/summer2.jpg' is not a directory Sorry, my mistake. It should read: find . -name *.jpg -type f -print0 | xargs -0 --replace mv '{}' /Photos/new As an aside, using find with -exec results in one forked process per file processed, wheras using xargs puts as many files as possible into one call to mv, so one forked process per many, many files. If you're moving lots of things around, you'll probably notice the difference. Edit: another thought, you can also use -i instead of --replace in your call to xargs. Edited February 12, 2009 by powdarrmonkey 2
CyberNerd Posted February 12, 2009 Posted February 12, 2009 As an aside, using find with -exec results in one forked process per file processed, wheras using xargs puts as many files as possible into one call to mv, so one forked process per many, many files. If you're moving lots of things around, you'll probably notice the difference. Thats useful to know, I never quite got the hang of xargs but will endeavor to learn!
RabbieBurns Posted February 12, 2009 Author Posted February 12, 2009 roberts Photos # find . -name *.jpg -type f -print0 | xargs -0 --replace mv '{}' /Photos/new find: paths must precede expression: 2.jpg Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression] roberts Photos # find . -name *.jpg -type f -print0 | xargs -0 -i mv '{}' /Photos/new find: paths must precede expression: 2.jpg Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression] I appreciate your help. (PS. The file 2.jpg is in /Photos/, which is where Im running the command)
powdarrmonkey Posted February 12, 2009 Posted February 12, 2009 Damn, it's really not going well for me today Wrap your *.jpg in quotes to stop bash interpreting it, like "*.jpg". Otherwise, bash tries to give find a list of files that it think it should be finding, and find gets grumpy. @Cybernerd: All it does it turn mv 1.jpg /tmp mv 2.jpg /tmp mv 3.jpg /tmp mv 4.jpg /tmp mv 5.jpg /tmp mv 6.jpg /tmp mv 7.jpg /tmp into mv 1.jpg 2.jpg 3.jpg 4.jpg 5.jpg 6.jpg 7.jpg /tmp but also does some sanity checking, like making sure that the list of arguments isn't so long as to cause a buffer overflow (in which case, splits it into two calls). 1
RabbieBurns Posted February 12, 2009 Author Posted February 12, 2009 Thats it! Works well. Many thanks
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now