FOR 루프 대신 WHILE 루프를 사용하여 파일 이름 바꾸기

FOR 루프 대신 WHILE 루프를 사용하여 파일 이름 바꾸기

같은 이름을 가진 사진이 많이 있다고 생각해 보세요 DSC_20170506_170809.JPEG. 패턴을 따르도록 사진의 이름을 바꾸기 위해 Paris_20170506_170809.JPEG완벽하게 작동하는 다음 스크립트를 작성했습니다.

for file in *.JPEG; do mv ${file} ${file/DSC/Paris}; done

제 질문은 루프 while대신 루프를 사용하여 for이 스크립트를 어떻게 작성할 수 있느냐는 것입니다.

답변1

여기에서는 루프를 사용하는 데 아무런 문제가 없습니다 while. 당신은 그것을 올바르게해야합니다 :

set -- *.jpeg
while (($#)); do
mv -- "${1}" "${1/DSC/Paris}"
shift
done

위의 루프는 while루프만큼 안정적이며 for(모든 파일 이름에서 작동함) 후자가 많은 경우에 사용하기에 가장 적합한 도구인 반면 전자는 용도가 있는 유효한 대안입니다(예: 위의 경우 세 개의


이러한 모든 명령( set, while..do..doneshift)은 쉘 매뉴얼에 문서화되어 있으며 해당 이름은 설명이 필요하지 않습니다.

set -- *.jpeg
# set the positional arguments, i.e. whatever that *.jpeg glob expands to

while (($#)); do
# execute the 'do...' as long as the 'while condition' returns a zero exit status
# the condition here being (($#)) which is arithmetic evaluation - the return
# status is 0 if the arithmetic value of the expression is non-zero; since $#
# holds the number of positional parameters then 'while (($#)); do' means run the
# commands as long as there are positional parameters (i.e. file names)

mv -- "${1}" "${1/DSC/Paris}"
# this renames the current file in the list

shift
# this actually takes a parameter - if it's missing it defaults to '1' so it's
# the same as writing 'shift 1' - it effectively removes $1 (the first positional
# argument) from the list so $2 becomes $1, $3 becomes $2 and so on...
done

1: 텍스트 처리 도구를 대체하는 것이 아니므로안 돼요루프를 사용하여 while텍스트를 처리합니다.

답변2

for-루프는 일반적으로 다시 완료됩니다.변화 없는데이터. 즉, 루프 도중이나 알려진 시간 간격 내에서는 데이터가 변경되지 않습니다.

while루프는 사용자에게 입력을 요청하고 정확할 때까지 응답의 유효성을 검사하거나 파일이나 파이프에서 읽은 데이터를 반복하는 등 반복이 필요한 횟수를 알 수 없을 때 자주 사용됩니다.

이 경우 쉘의 확장 파일 글로빙 패턴에 따라 현재 디렉토리에서 직접 읽은 파일 이름을 반복하고 있습니다. 루프는 for올바르게 사용되는 루프 구조입니다. 루프는 while상황을 복잡하게 만들고 코드를 올바르게 읽고 실행하기 어렵게 만듭니다.

다음은 while루프와 동일한 작업을 수행하는 루프의 예 입니다 for.

printf '%s\n' DSC*.JPEG |
while read -r name; do
    [ ! -f "Paris${name#DSC}" ] && mv "$name" "Paris${name#DSC}"
done

여기에 뭔가 문제가 있습니다.

  1. 루프는 줄바꿈으로 구분된 이름을 읽기 때문에 파일 이름에는 줄바꿈이 포함될 수 없습니다. printf출력으로 \0구분된 파일 이름을 가져 와서 read읽으면 이 문제를 해결할 수 있지만 이렇게 하면 문제가 더 복잡해지고 이식성이 떨어집니다.
  2. 아무것도 얻지 못했습니다. 이름 목록은 여전히 ​​정적이며 이러한 이름을 printf루프에 전달하는 중복 단계를 도입했습니다. 이로 인해 파일 이름에 어떤 문자를 허용할 수 있는지에 대한 질문이 제기됩니다(이전 항목 참조).

실제로 코드의 유일한 문제는 변수 확장이 인용되지 않았다는 것입니다.

답변3

until원하는 경우 Bash 루프를 사용할 수도 있습니다.

set -- *.jpeg
until ((! $#))
do
    mv -- "${1}" "${1/DSC/Paris}"
    shift
done

관련 정보