이 명령을 사용하여 디렉토리의 모든 이미지를 몽타주합니다.
gmic *jpg -gimp_montage 4,\""V(H(0,1),H(2,V(3,4)))"\",1,1.0,0,5,0,0,0,255,0,0,0,0 -o -0000."$(date)".jpg
이 명령을 디렉터리와 해당 하위 디렉터리에서 반복적으로 실행하고 싶습니다. 따라서 각 디렉토리에서 해당 디렉토리에 있는 이미지의 몽타주를 생성하겠습니다.
나는 시도했다:
find -exec gmic *jpg -gimp_montage 4,\""V(H(0,1),H(2,V(3,4)))"\",1,1.0,0,5,0,0,0,255,0,0,0,0 -o -0000."$(date)".jpg
하지만 이로 인해 오류가 발생했습니다.
find: missing argument to `-exec'
나도 시도했다
find -exec gmic -gimp_montage 4,\""V(H(0,1),H(2,V(3,4)))"\",1,1.0,0,5,0,0,0,255,0,0,0,0 -o -0000."$(date)".jpg {} \;
이로 인해 다음과 같은 오류가 발생합니다.
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ Output image [] as file '-0000.Fri Mar 13 04:33:44 EDT 2015.jpg', with quality 100%.
[gmic]-0./ *** Error *** Command '-output': File '-0000.Fri Mar 13 04:33:44 EDT 2015.jpg', instance list (0,(nil)) is empty.
[gmic] *** Error in ./ *** Command '-output': File '-0000.Fri Mar 13 04:33:44 EDT 2015.jpg', instance list (0,(nil)) is empty.
답변1
좋습니다. 디렉토리 트리의 모든 디렉토리(현재 디렉토리, 하위 디렉토리, 하위 디렉토리 등)에서 명령을 실행하려고 합니다. 가장 먼저 해야 할 일은 문제의 디렉터리를 열거하는 것입니다. find
디렉토리만 나열하도록 지시하려면 다음 명령을 사용하십시오 .
find . -type d
각 디렉토리에서 실행하려는 명령은 다음과 같습니다.
gmic ./*jpg -gimp_montage 4,\""V(H(0,1),H(2,V(3,4)))"\",1,1.0,0,5,0,0,0,255,0,0,0,0 -o -0000."$(date)".jpg
이는 와일드카드 확장 및 명령 대체를 포함하는 쉘 명령입니다. 이를 실행하려면 쉘을 실행해야 합니다. 쉘이 무엇을 해야할지 지시받을 것이기 때문에 , 당신이 실행하고 있는 쉘 find
은 아닐 것입니다 . 쉘을 실행하라고 지시해야 합니다. 쉘 인수로 제공하려는 디렉토리를 쉘에 전달하십시오.find
find
find . -type d -exec sh -c '…' {} \;
이 스크립트 를 호출하기 전에 gmic
이 스크립트에서 몇 가지 작업을 수행해야 합니다 . 관련 디렉터리로 변경하고 .jpg
파일이 포함되어 있는지 확인합니다.
find . -type d -exec sh -c '
cd "$0" || exit
set -- *.jpg
if [ -e "$1" ]; then
gmic "$@" -gimp_montage 4,\""V(H(0,1),H(2,V(3,4)))"\",1,1.0,0,5,0,0,0,255,0,0,0,0 -o -0000."$(date)".jpg
fi
' {} \;
또는 파일을 find
나열하도록 지시할 수 있습니다. .jpg
그러나 이로 인해 디렉터리당 하나의 명령만 실행하기가 어렵습니다.
쉘이 plain이 아닌 bash인 경우 와일드카드를 사용하여 디렉토리로 재귀할 sh
수 있습니다 . **
를 사용하는 것보다 쉽습니다 find
. Bash 4.2 이하에서는 **
디렉터리의 기호 링크를 탐색하는 데에도 주의하세요 . 파일 존재 테스트를 약간 단순화할 수도 있습니다.
shopt -s globstar nullglob
for dir in ./**/*/; do
files=("$dir/"*.jpg)
if [[ ${#files[@]} -ne 0 ]]; then
gmic "${files[@]}" -gimp_montage 4,\""V(H(0,1),H(2,V(3,4)))"\",1,1.0,0,5,0,0,0,255,0,0,0,0 -o "$dir/-0000.$(date)".jpg
fi
done
zsh에서는 사용할 수 있습니다기록 수정자안에글로벌 예선파일이 포함된 디렉터리를 열거한 .jpg
다음 결과 배열을 필터링하여 각 디렉터리의 단일 복사본을 유지합니다.
dirs=(./**/*.jpg(:h))
for dir in ${(u)dirs}; do
gmic $dir/*.jpg -gimp_montage 4,\""V(H(0,1),H(2,V(3,4)))"\",1,1.0,0,5,0,0,0,255,0,0,0,0 -o "$dir/-0000.$(date).jpg"
done
(여담: -0000.Sat Mar 14 15:51:28 CET 2015.jpg
그것은 파일에 대한 매우 이상한 이름입니다. 이름이 로 시작하는 파일은 -
명령에 대한 옵션처럼 보이기 때문에 문제를 일으키는 경향이 있습니다. 사전순으로 정렬하는 것은 연대순으로 정렬하는 것과 동일한 형식으로 날짜에 대해 더 편리하게 작동합니다 20150314-145128
. 예를 들어 .)
답변2
나머지 의견과 마찬가지로 -exec 이외의 명령을 실행하거나 비트를 while 또는 for 루프로 파이프하려면 무엇이 필요한지 잘 모르겠습니다. exec 옵션을 사용하면 찾은 모든 항목(상대 경로가 아닌 전체 경로) 대신 "{}"를 사용할 수 있습니다. 다음은 -exec 옵션과 for 루프의 간단한 예입니다.
$ tree
.
|-- a
| |-- a
| | `-- a
| `-- b
`-- b
|-- a
`-- b
7 directories, 0 files
$ find . -type d -exec touch {}/foo \
$ tree
.
|-- a
| |-- a
| | |-- a
| | | `-- foo
| | `-- foo
| |-- b
| | `-- foo
| `-- foo
|-- b
| |-- a
| | `-- foo
| |-- b
| | `-- foo
| `-- foo
`-- foo
7 directories, 8 files
$ for i in $(find . -type f); do mv $i $i.moved; done
$ tree
.
|-- a
| |-- a
| | |-- a
| | | `-- foo.moved
| | `-- foo.moved
| |-- b
| | `-- foo.moved
| `-- foo.moved
|-- b
| |-- a
| | `-- foo.moved
| |-- b
| | `-- foo.moved
| `-- foo.moved
`-- foo.moved
7 directories, 8 files