일반적으로 특정 작업을 위한 쉘 스크립트를 작성할 때 다음과 같은 파일 목록을 만듭니다.
#/bin/sh
read -d '' imagefiles <<EOF
./01/IMG0000.jpg
./01/IMG0001.jpg
./01/IMG0002.jpg
./01/IMG0003.jpg
./01/IMG0004.jpg
./01/IMG0005.jpg
./01/IMG0006.jpg
./01/IMG0007.jpg
(a whole bunch of files down to ./10/IMG0102.jpg)
EOF
for i in $imagefiles
for j in range(len(commands))
do
mv $i ./$j.jpg
done
done
이 경우 출력을 반복할 수 있기를 원 seq
하지만 Gilles가 제안한 대로 이 부분을 Python으로 작성하세요(예, 각 명령이 j번 실행되어 약 100,000번 실행된다는 것을 알고 있습니다). 이전에는 736개의 파일을 순서대로 이름을 바꿨는데 지금은 이름을 바꿀 파일이 1000개가 넘습니다. 이 작업을 수행하는 더 좋은 방법이 있다고 확신하지만(주저하지 말고 알려주세요) 명령 목록과 기타 반복 가능한 항목을 반복하는 방법을 아는 것도 좋을 것입니다.
답변1
좋습니다. 두 개의 반복 가능 항목을 압축하려고 합니다. 즉, 추가 카운터를 사용하여 여러 문자열을 반복하는 루프를 원합니다. 카운터를 구현하는 것은 매우 쉽습니다.
n=0
for x in $commands; do
mv -- "$x" "$n.jpg"
n=$(($n+1))
done
이는 반복하려는 요소에 공백(또는 와일드카드)이 포함되어 있지 않은 경우에만 작동합니다. 항목이 줄바꿈으로 구분된 경우 와일드카드를 끄고 줄바꿈으로만 분할하세요.
n=0
IFS='
'; set -f
for x in $commands; do
mv -- "$x" "$n.jpg"
n=$(($n+1))
done
set +f; unset IFS
데이터를 한 번만 반복해야 한다면 루프를 실행하세요 read
(참조:while IFS= read
대신 왜 그렇게 자주 사용됩니까 IFS=; while read..
?자세한 설명은)
n=0
while IFS= read -r x; do
mv -- "$x" "$n.jpg"
n=$(($n+1))
done <<EOF
…
EOF
배열(bash, ksh 또는 zsh)이 있는 셸을 사용하는 경우 배열에 요소를 저장합니다. zsh에서 setopt ksh_arrays
0부터 시작하는 번호가 매겨진 배열 요소를 실행하거나 1부터 시작하는 배열 요소 번호 매기기를 시작하도록 코드를 조정합니다.
commands=(
./01/IMG0000.jpg
…
)
n=0
while [[ $n -lt ${#commands} ]]; do
mv -- "${commands[$n]}" "$n.jpg"
done
답변2
쉘이 이면 bash
이 프로그램을 실행할 필요가 없습니다 seq
. 그냥 사용
for i in {1..736}
do
앞에 0이 있는 시퀀스를 원하면 {001..736}
(even {0001..0736}
)만 사용하세요.
또한 가능하면 백틱(이것이 어떻게 일을 엉망으로 만드는지 보려면 이 질문을 참조하세요.).
또 다른 점은 파일 그룹을 조작하려는 경우 이 기능이 유용할 수 있다는 것입니다.
for file in /some/path/*
do
모든 파일에서 작동합니다(및 폴더)디렉토리에 /some/path/
. 범위를 파일로만 좁히려면 다음 [ -f "$file" ]
과 같은 유사한 테스트를 사용할 수 있습니다.
for file in /some/path/*
do
[ -f "$file" ] || continue
(do your stuff here)
또한 구성은 /some/path/*
와 같은 셸 모드를 통해 조정될 수 있습니다./some/path[123]/*
/some/path[A-Z]/b*[e-g]*
/some/path{1,5,23}/*
질문의 첫 번째 부분에 관한 한 다음 과 같이 중첩된 for
(또는 임의의) 루프를 사용할 수 있습니다.while
for cm in $commands; do
for file in /some/path[ab]{1,4,2}/*.log; do
mv "${file}" "${file//text/replacement}"
done
done
답변3
Bash에서는 여러 작업을 병렬로 반복할 수 없다고 생각합니다.
시작하겠습니다 i=1
. 그런 다음 파일 목록이 반복되어 let i=$i+1
루프에 포함됩니다. $i -ge 736
또한 루프 카운트 이후 입력된 항목에 대한 반복을 중지하려는 경우 루프를 중단하는 테스트도 포함됩니다.
i=0
for file in ./{01..10}/*jpg; do
let i=$i+1
mv "$file" "$i-$file"
done
X 파일을 닫으려고 하면 다음과 같은 테스트를 사용할 수 있습니다.
[[ $i -ge 736 ]] && return || let i=$i+1
답변4
Bash는 배열을 지원합니다:
http://tldp.org/LDP/abs/html/arrays.html
또는
COUNT=0
for i in `ls *.txt`
do
COUNT=`expr $COUNT + 1`
mv "$i" "$COUNT-$i"
done
그러면 a.txt b.txt c.txt 파일의 이름이 1-a.txt 2-b.txt 3-c.txt로 변경됩니다.