동일한 이름을 가진 기존 파일이 있는 경우 파일의 새 이름을 생성하는 방법은 무엇입니까? 데스크탑 환경에서는 파일 이름 끝에 숫자를 추가하여 새 이름을 생성하는데, 명령줄에서는 어떻게 이를 수행할 수 있습니까?
저는 Android OS와 Busybox를 사용하고 있습니다.
답변1
POSIX 쉘이 있다고 가정하면 다음을 수행할 수 있습니다.
mv() {
eval "DEST=\${$#}" #The destination is the last positional parameter
if [ -e "$DEST" ] && ! [ -d "$DEST" ];then
PREFIX=${DEST%.*}
COUNT=1
EXT=${DEST##*.}
args= i=1
while [ $i -lt $# ]; do args="$args \"\${$i}\"" i=$((i+1)); done
DEST="$NAME-"$(printf "%03d" $COUNT)".$EXT"
while [ -e "$DEST" ];do
COUNT=$((COUNT+1))
DEST="$NAME-"$(printf "%03d" $COUNT)".$EXT"
done
eval "command mv $args \"\$DEST\""
else
command mv "$@"
fi
}
이것을 사용하는 방법
이것은 함수이므로 파일에 저장 ~/.bashrc
하고 평소처럼 사용하세요 mv
.
이것은 무엇을 위한 것인가?
- 원래 실행 파일의 경로를 변수
mv
에 저장합니다.MV
- 변수로 호출하는 마지막 매개변수를 가져옵니다.
DEST
- 디렉토리가 존재하고 디렉토리가 아닌 경우
DEST
, 이 함수는 이름 바꾸기가 파일을 손상시키려고 한다고 가정합니다. - 그런 다음 최종 이름의 접두사(최종 이름 앞의 모든 항목
.
, 확장명 표시), 확장자(최종 이름 뒤의 모든 항목.
), 개수(있는 경우 최종 이름 뒤의 접두사에 있는 모든 항목-
)를 추출합니다. - 추출된 개수는 개수가 없으면 0으로 설정되고, 그렇지 않으면 이전 단계에서 찾은 개수로 설정됩니다.
- 현재 카운트 증가
- 그런 다음 함수는 모든 원래 인수(스위치 + 파일 이름)에서 마지막 인수를 뺀 값으로 자신을 호출하고 원래 호출의 마지막 인수 대신 새 파일 이름을 추가합니다. 새 이름은 이전 이름이지만 확장자 앞에 3자리 카운터가 추가됩니다(제로 패딩).
- 함수는 재귀적입니다. 왜냐하면 다음 호출은 함수 자체여야 하기 때문입니다. 함수가 존재하는 경우 존재하지 않는 새 파일 이름이 발견될 때까지 카운터를 계속 증가시키려고 하기 때문
mv a.txt b.txt
입니다 .mv a.txt b-001.txt
mv
b-001.txt
- 마지막 인수가 존재하지 않거나 디렉터리인 경우
mv
원래 실행 파일은 원래 인수를 사용하여 호출됩니다.
지침
- 기존 파일을 손상시키려고 반복적으로 시도할 수 있는 횟수는 카운터 길이에 따라 다릅니다(이 경우 999회). 파일을 생성할 수 있는 동안 작동하도록 하려면 파일 시스템의 inode 제한을 포함하는 숫자를 선택할 수 있습니다.
- 와 유사한 이름을 가진 파일을 손상시키려고 하면
foo-001.txt
.foo-001-001.txt
노트
- 명명 패턴을 변경하려면 명령문을 원하는 대로
3
변경하세요 .printf
- 이 코드는 테스트되었습니다.
- 이것은 매우 간단하며 일부 극단적인 경우에는 심하게 실패할 것이라고 확신합니다. 문제가 발견되면 기꺼이 해결해 드리겠습니다. 또한 프로덕션 시스템에서는 이 작업을 시도하지 마세요.
답변2
나는 보통 이 도구를 사용하여 mktemp
안정적인 임시 파일을 만듭니다. 기본적으로 파일을 생성하지만 -d
스위치를 통해 디렉터리를 생성할 수도 있습니다.
예
현재 디렉터리에 있는 파일의 임시 이름을 만드는 방법은 다음과 같습니다.
$ mktemp somefile.XXXXX
somefile.kiDad
$ mktemp somefile.XXXX
somefile.MrSW
$ mktemp someotherfile.XXXXXXXXXXX
someotherfile.Um4aXKrt3lv
그러면 파일이 생성됩니다.
인용하다
답변3
경고 없이 Joseph의 R 스크립트에 대한 대안이 있습니다! 경로 이름에 숫자 접미사를 추가하고(경로는 디렉터리 또는 파일일 수 있음) 아직 존재하지 않는 접미사를 찾을 때까지 접미사 값을 증가시킵니다. logrotate
비슷한 패턴을 사용하지만 새 복사본의 접미사가 항상 "0"이 되도록 기존 복사본을 모두 회전하는 등의 기타 유틸리티도 있습니다 . 이것은 그런 의미에서 회전이 아니기 때문에 이라고 부르 겠습니다 dotmv
.file.0
가장 오래된복사.
예를 들어:
dotmv somefile.txt
rename somefile.txt
somefile.txt.0
, 후자가 존재하지 않는 한, 존재하는 경우에는 somefile.txt.1
가 됩니다. 여러 파일( dotmv this that "the other thing"
등) 을 나열할 수 있으며 모든 파일이 클릭되어 이동됩니다.
나는 이것이 POSIX와 호환된다고 믿습니다. 이것은 set -o posix
bash에서 실행됩니다(그러나 이것은 모호한 테스트입니다). 나는 또한 안드로이드(jelly bean 4.2.1) 쉘로 테스트했고 거기서 작동했습니다. 그러나 Android에서는 shebang을 변경하거나 실행하려면 지침을 따라야 합니다 sh dotmv
. 루팅된 장치가 없으면 스크립트를 실행 가능하게 만들 수 있는 방법이 없기 때문에 어쨌든 이 작업을 수행하게 됩니다. shebang을 변경하면 exec dotmv
.
#!/bin/sh
# On android change that to /system/bin/sh.
# Validate arguments
if [ $# -lt 1 ]; then
echo "A list of one or more paths is required."
exit 1
fi
# Checks if a path exists and can be moved.
checkPath () {
if [ ! -e "$1" ]; then
echo "'$1' does not exist."
return 1;
fi
if [ ! -w "$1" ]; then
echo "Cannot move '$1', permission denied."
return 1;
fi
return 0;
}
# Finds a new path with numerical suffix.
getName () {
suf=0;
while [ -e "$1.$suf" ]
do let suf+=1
done
Dest=$1.$suf
}
# Loop through arguments -- use quotes to allow spaces in paths.
while (($#)); do
Src=$1
Dest=$1
shift
checkPath "$Src"
if [ $? -eq 0 ]; then
getName "$Src"
mv "$Src" "$Dest"
fi
done
여기의 논리는 매우 간단하기를 바랍니다. 이는 Python, C 또는 파일 I/O가 있는 기타 Turing-complete 절차 언어로 구현될 수 있습니다.