I have a main folder that contains files and subfolders and I want to move all the graphic files (pdf
, png
, jpg
, and so on) in a new folder callded figs
(inside my main folder).
I want to exclude:
- all the subfolders whose name starts with
Copy_of_
- all the folders whose name contains
copy 1
andtikz
- all the
pdf
files whose name starts withCopy_of_
,XXX
,YYY
,ZZZ
I wrote this code:
# not pdf
find . -type f -regextype posix-extended -regex '.*(jbig2|jpeg|jp2|jpg|jpx|png)$' ! -path '*/Copy_of_*/*' ! -path '*/*copia 1*/*' ! -path '*/tikz*/*' ! -path 'figs' -print0 | xargs -0 -I {} mv {} "figs"
# pdf
find . -type f \( -name "*.pdf" ! -name "Copy_of_*" ! -name "XXX*" ! -name "YYY*" ! -name "ZZZ*" \) ! -path '*/Copy_of_*/*' ! -path '*/*copy 1*/*' ! -path '*/tikz*/*' ! -path 'figs' -print0 | xargs -0 -I {} mv {} "figs"
I split my code into two parts because I can't manage it in one solution.
Is there a way to do it all with one call to find
and/or to use regular expressions for -name
and -path
thus avoiding having to specify them one by one?
CodePudding user response:
You can do a lot of complex things when you go to town with grouping expressions (as you already did in your first find
command, along with -and
and -or
). Check out the OPERATORS
section of its man-page.
Something like this, for instance:
#!/bin/bash
find \
. -type f \
! -path '*/Copy_of_*/*' \
! -path '*/*copia 1*/*' \
! -path '*/tikz*/*' \
! -path 'figs' \
\( \( -regextype posix-extended -regex '.*(jbig2|jpeg|jp2|jpg|jpx|png)$' \) -or \
\( -name "*.pdf" ! -name "Copy_of_*" ! -name "XXX*" ! -name "YYY*" ! -name "ZZZ*" \) \) \
-print0 | \
xargs -0 -I {} echo {}
This test snippet merely echo
s the files that it thinks it should move. For a quick test I created some (empty) files:
$ tree
.
|-- Copy_of_figs
| `-- 1.jpg
|-- Copy_of_pdf_1.pdf
|-- Hello
| |-- 1.jpg
| |-- 2.png
| `-- 3.pdf
|-- figs
|-- snippet.sh
`-- tikz
`-- 4.pdf
4 directories, 7 files
Where this was the result:
$ ./snippet.sh
./Hello/2.png
./Hello/1.jpg
./Hello/3.pdf
Sidenote: You refer to copia 1
in one find
statement and to copy 1
in another. Don't know if the former was a typo, or if both patterns needed to be excluded.