파일 이름을 자동으로 증가시킵니다.

파일 이름을 자동으로 증가시킵니다.

일부 중복 파일을 수집해야 하며 이름 충돌을 피하고 싶습니다. 문제는 파일이 정리되기 전에 내 스크립트를 다시 실행하여 이 파일 모음이 추가될 수 있으며 계속해서 숫자를 늘리려는 것입니다.

나는 아래와 같이 숫자를 증가시키기 위해 간단한 Until 루프를 사용하기로 결정했습니다.

until [[ ! -f ${PWD}/DUPES/${num}-$1 ]]; do
num=$((num +1))
done
mv --no-clobber $1 ${PWD}/DUPES/${num}-$1

극단적인 경우 파일이 1k를 넘을 것이라고는 상상할 수 없습니다. 그래서 제 질문은...

이것이 이를 달성하는 데 매우 비효율적인 방법입니까? 거기에서 증가할 가장 높은 선행 숫자를 얻기 위해 기존 파일을 구문 분석해야 합니까, 아니면 제가 제시한 극단적인 예에 ​​대해 괜찮습니까? 아니면 더 좋은 방법이 있나요?

답변1

GNU mv에는 --backup유용할 수 있는 옵션이 있습니다. 다음 상호 작용은 대상이 존재할 때 파일 이름을 바꾸는 방법을 보여줍니다.

$ touch a b c o
$ mv --backup=numbered --verbose a o
`a' -> `o' (backup: `o.~1~')
$ mv --backup=numbered --verbose b o
`b' -> `o' (backup: `o.~2~')
$ mv --backup=numbered --verbose c o
`c' -> `o' (backup: `o.~3~')

이 예에서는 원본 파일의 이름이 , to , to 및 to o로 변경되었습니다 . 따라서 게시한 코드와 동일한 방식으로 이름이 바뀌지는 않지만 특정 요구 사항에 따라 허용될 수 있습니다.o.~1~ao.~2~bo.~3~co

답변2

다음을 수행할 수 있습니다.

set -C; num=0                                  ### set -o noclobber; init $num
[ -e "$1" ] &&                                 ### this needs to be true
until 2>&3 >"./DUPES/$((num+=1))-$1" &&        ### try to open() num+=1
      mv --  "$1"  "./DUPES/$num-$1"           ### if opened, mv over it
do :; done 3>/dev/null                         ### do nothing

여러 인스턴스가 특정 파일의 이름이 동일한지 확인하고 변수를 증가시킬 수 없는지 즉시 확인합니다.

< /dev/nullstderr는 출력 잘림/리디렉션을 수행하고 기존 대상을 찾으려고 할 때 파일 존재에 대한 쉘의 불만 사항을 제거합니다. 하지만노클로보활성화되면 다른 파일을 덮어쓰지 않습니다. 를 open()사용하지 않는 한 새 파일 만 덮어씁니다 >|. 따라서 존재하지 않는 이름이 발견될 때까지 기존 파일을 증가시키는 것이기 때문에 불평할 필요가 없습니다.

성능에 관해서 - 그것회의처음부터 시작하지 않는 것이 좋습니다. 아니면 차이를 메우려고 하는 경우. 위의 내용이 개선될 수 있다고 생각합니다. 예를 들면 다음과 같습니다.

set -C; num=0                                  ### set -o noclobber; init $num
until 2>&3 >"./DUPES/$((num+=1))-$1"  &&       ### try to open() num+=1
      mv --  "$1"  "./DUPES/$num-$1"           ### if opened, mv over it
do    [ -e  "./DUPES/$((num*2))-$1" ] &&       ### halve fail distance
      num=$((num*2))                           ### up to a point of course
done  3>/dev/null                              ### done

...하지만 1000개 이내에서는 너무 걱정할 필요가 없습니다. 몇 초 만에 65,000개가 넘는 무작위 이름을 얻었습니다.

그런데 - 당신은 다음을 할 수 있다고 생각할 수도 있습니다:

>"./DUPES/$((num+=1))-$1" mv -- "$1" "./DUPES/$num-$1"

...하지만 쉘에서는 작동하지 않습니다 bash.

num=0; echo >"/tmp/$((num+=1))" >&2 "$num"; echo "$num" /tmp/[01]

0
1 /tmp/1

어떤 이유로든 bash리디렉션 할당은 다른 컨텍스트에서 발생하므로 확장은 이상한 순서로 발생합니다. 따라서 올바른 $num값을 확장하려면 별도의 간단한 명령이 필요합니다 &&. 그렇지 않으면 다음과 같습니다.

num=0; echo "$((num+=1))" "$num"

1 1

답변3

동시에 실행되고 동시에 실행되는 두 개의 제안 인스턴스를 고려해보세요. 그들은 모두 num=4가 사용 가능하다는 사실을 발견하고 모두 동일한 대상 이름을 사용하려고 시도할 것입니다.

지금은 이 대안을 테스트할 수 없지만 이와 같은 것으로 충분할 수 있습니다.

num=1 attempt=10
while ! mv --no-clobber "$1" "${PWD}/DUPES/${num}-$1" && [[ 0 -lt $attempt ]]
do
    num=$((num+1))
    attempt=$((attempt-1))
done
[[ 0 -eq $attempt ]] && echo "ERROR: Too many attempts to handle $1" >&2

관련 정보