View Full Version : Simple bash script: move by file extension.
sebastian.s
February 10th, 2013, 02:29 AM
I have just recently started with Bash scripting, and i am trying to move files according to their file extension. Directly at the bash prompt i can do like this:
mv *+(.jpg|.jpeg|.gif|.png) ./picturesbut if i try the same in my script i get a syntax error, this is what the script look like:
mv *+(.mp3) ./music
mv *+(.jpg|.jpeg|.gif|.png) ./pictures
mv *+(.doc|.pdf|.odt|.txt) ./document
mv *+(.deb|.zip|.gz) ./packets
mv *+(.iso) ./iso-files
exit 0Why is that?
cwsnyder
February 10th, 2013, 02:32 AM
I think your script syntax is aborting on your .mp3 and .iso lines where you only have one option, but you are inserting the + and () which implies multiple options.
Vaphell
February 10th, 2013, 03:06 AM
why don't you use standard globs
mv *.jpg *.jpeg *.gif *.png ./pictures
or
mv *.{jpg,jpeg,gif,png} ./pictures
sisco311
February 10th, 2013, 06:36 AM
+1 for standard globs or brace expansion.
If you want to use extended globs, you have to enable them:
shopt -s extglob
See:
http://mywiki.wooledge.org/glob?action=show&redirect=globbing
http://mywiki.wooledge.org/BraceExpansion
Merrattic
February 10th, 2013, 01:58 PM
Have a look here, might give you some help:
http://ubuntuforums.org/showthread.php?t=2086723
sudodus
February 10th, 2013, 02:25 PM
There might be a problem with file names containing spaces.
I tested the following command line, and it works with such file names
for i in *+(.doc|.pdf|.odt|.txt);do ls "$i";done
and you can replace
do ls "$i" with do mv "$i" ./documents
Vaphell
February 10th, 2013, 04:03 PM
no, globs are not sensitive to whitespaces at all (that's why they should be used directly as often as possible)
$ touch "test 1.txt" "test 2.txt" "test 1.pdf"
$ printf "[%s]\n" *.{txt,pdf}
[test 1.txt]
[test 2.txt]
[test 1.pdf]
$ shopt -s extglob
$ printf "[%s]\n" *+(.txt|.pdf)
[test 1.pdf]
[test 1.txt]
[test 2.txt]
sudodus
February 10th, 2013, 04:45 PM
I see, but maybe don't see ;-)
Running a script file containing
ls *+(.doc|.pdf|.odt|.txt) or
for i in *+(.doc|.pdf|.odt|.txt);do ls "$i";done
won't work when run by bash
bash script
but runs without problems when run by source
source script
Please explain the difference!
sisco311
February 10th, 2013, 04:57 PM
There might be a problem with file names containing spaces.
EDIT: Yayy! Didn't refresh the page before posting. Vaphell beat me to it.
Nope. The file names produced by the glob do not undergo any further word-splitting, so even if a file contains internal whitespace, the expansion of a glob that matches that file will still preserve each filename as a single word.
If the glob does not match any file name and nullglob is not enabled then it remains unchanged. In this case mv will throw a `no such file or directory' error which can be safely ignored.
sisco311
February 10th, 2013, 05:07 PM
I see, but maybe don't see ;-)
Running a script file containing
ls *+(.doc|.pdf|.odt|.txt) or
for i in *+(.doc|.pdf|.odt|.txt);do ls "$i";done
won't work when run by bash
bash script
but runs without problems when run by source
source script
Please explain the difference!
`bash script' will run the script in a subshell where extglob is not enabled. You have to enable it in your script:
shopt -s extglob
commmand *+(whatever)
The `source' command or the dot (`.') command will run the commands from the script in the current shell.
sudodus
February 10th, 2013, 05:14 PM
`bash script' will run the script in a subshell where extglob is not enabled. You have to enable it in your script:
shopt -s extglob
commmand *+(whatever)
The `source' command or the dot (`.') command will run the commands from the script in the current shell.
Thank you :-)
sebastian.s
February 10th, 2013, 05:39 PM
Setting the shell options to extended fixed it the way i chose to do it, i found that method in the book i'm reading right now and i missed that i had to enable extglob.
If you want to use extended globs, you have to enable them:
shopt -s extglob
And of course using the standard globbings worked just fine aswell, thanks for the tip :)
why don't you use standard globs
mv *.jpg *.jpeg *.gif *.png ./picturesor
mv *.{jpg,jpeg,gif,png} ./pictures
Powered by vBulletin® Version 4.2.2 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.