When I import pictures from my camera in Shotwell, it also imports the video clips. This is somewhat annoying, as I would like to store my videos in another folder. I've tried to write a bash command to do this, but have not had success.
I need a command that meets the following requirements:
- Locate all files in a directory structure that do not have an extension of .jpg, .png, .gif, or .xcf (case insensitive).
- Move all of these files into a target directory, regardless of whether the file names or directory paths contain spaces or special characters.
Any help would be appreciated!
EDIT: I'm using the default shell in Ubuntu, meaning that some commands are aliased, etc.
EDIT 2: I've attempted this myself (not the copy part, just the listing of files part). I turned on extglob and ran the following command:
$ ls -R /path | awk '
/:$/&&f{s=$0;f=0}
/:$/&&!f{sub(/:$/,"");s=$0;f=1;next}
NF&&f{ print s"/"$0 }'
This lists everything. I tried using grep on the end of it, but haven't the foggiest idea of how to get it to not match a pattern I give it. The extglob switch didn't help much with grep, even though it does help with other commands.
Best Answer
You can use
find
to find all files in a directory tree that match (or don't match) some particular tests, and then to do something with them. For this particular problem, you could use:This limits the search to regular files (
-type f
), and then to files whose names do not (!
) have the extension*.png
in any casing (-iname '*.png'
) or (-o
)*.gif
, and so on. All the extensions are grouped into a single condition between\( ... \)
. For each matching file it runs a command (-exec
) that moves the file, the name of which is inserted in place of the{}
, into the directory/new/path
. The\;
tellsfind
that the command is over.The name substitution happens inside the program-execution code, so spaces and other special characters don't matter.
If you want to do this just inside Bash, you can use Bash's extended pattern matching features. These require that
shopt extglob
is on, andglobstar
too. In this case, use:This matches all files in subdirectories (
**
) that do not match*.gif
,*.png
, etc, in any combination of character cases, and moves them into the new path. The expansion is performed by the shell, so spaces and special characters don't matter again.The above assumes all files are in subdirectories. If not, you can repeat the part after
**/
to include the current directory too.There are similar features in
zsh
and other shells, but you've indicated you're using Bash.(A further note: parsing
ls
is never a good idea - just don't try it.)