다음과 같은 파일 번호 목록이 있습니다.
01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
03_file_name.log
03_file_name.txt
04_file_name.log
04_file_name.txt
05_file_name.log
05_file_name.txt
03*
모든 파일 에 04*
새 파일을 삽입하고 싶습니다 . 따라서 와드 번호부터 시작하여 03
모든 파일을 이동/이름 변경해야 하며 앞에 오는 번호를 2씩 늘려야 합니다. 따라서 목록은 다음과 같습니다.
01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
05_file_name.log
05_file_name.txt
06_file_name.log
06_file_name.txt
07_file_name.log
07_file_name.txt
나는 다음과 같은 것을 생각하고 있습니다.
bash script.sh 03 02
while 03
은 $1
시작할 파일 이름의 번호와 추가할 번호입니다 02
. $2
중첩을 통해 이를 달성하려고 했지만 루프가 와드에서 지정된 번호의 파일만 실행하도록 하기 위해 for-loop
카운터를 사용하는 조합을 포기해야 했습니다 .((++))
답변1
이것이 당신이 원하는 것입니다. 한 가지: BASH에서만 작동하는 것 같아요.
MAXDIGITS
선택 사항이므로 세 자리 이상을 사용해야 하는 경우를 대비해 넣었습니다. 사용하지 않는 경우 해당 줄을 삭제하세요.
#!/bin/bash
BOTTOM=$1
SHIFT=$2
MAXDIGITS=0$3
for filename in $(ls -r *.{txt,log}); do
PREFIX=${filename%%_*}
NEWPREFIX=$(expr $PREFIX + $SHIFT)
if [ $PREFIX -ge $BOTTOM ]; then
NEWPREFIX=$(printf %${MAXDIGITS}d $NEWPREFIX)
mv $filename ${NEWPREFIX}_${filename#*_}
fi
done
지침:
./myscript <BOTTOM> <SHIFT> <MAXDIGITS>
### Example:
./miscript 03 02 2 #This means "Start at 03_filename.*, shift the prefixes by 2 and use 2 digits to construct the new prefixes".
동일한 디렉터리에 동일한 구문(prefix_filename.{txt,log})을 따르지 않는 다른 파일이 있는 경우 필터링해야 합니다. 그리고 접두사와 파일명을 구분하기 위해 "_"를 사용했기 때문에 이를 변경하면 코드를 수정해야 합니다.
답변2
그만한 가치가 있기 때문에 이것은 bash
두 가지가 포함된 하나의 라이너 입니다.프로세스 교체매우 간단한 awk
프로세스입니다.
$ ls -r -1 *_file_name.{txt,log} # list initial files in reverse order
05_file_name.log
05_file_name.txt
04_file_name.log
03_file_name.txt
03_file_name.log
03_file_name.txt
02_file_name.log
02_file_name.txt
01_file_name.log
01_file_name.txt
$ source <(awk 'BEGIN{FS="_"} $1>2 {prefix=$1+2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}' <(ls -r -1 *_file_name.{log,txt}))
$ ls -1 *_file_name.{txt,log} # list resulting files
01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
05_file_name.log
05_file_name.txt
06_file_name.log
06_file_name.txt
07_file_name.log
07_file_name.txt
설명하다:
위의 줄은 오른쪽에서 왼쪽으로 읽거나 적어도 "이해"됩니다.
ls -r -1 *_file_name.{log,txt}
처리할 모든 파일을 1열 형식으로 역순으로 나열합니다.
파일 접두사(기호로 표시*
)에 숫자가 아닌 문자가 포함되어 있으면 예상치 못한/원치 않는 결과가 발생할 수 있습니다. 이를 방지하려면 이 단계에서 처리할 파일을 필터링하세요.<(...)
공예 대체. 파일 설명자, 명명된 파이프라는 특수 임시 파일을 사용하여 이전 결과 출력을 참조할 수 있습니다. 자세한 내용은man bash
터미널에 게시하세요 .awk
스크립트:BEGIN{FS="_"}
레코드 처리를 시작하기 전에 레코드의 필드 구분 기호를 "_"(awk의 첫 번째 블록)로 설정하세요.awk
두 번째 블록의 조건$1>2
: 파일 이름 접두사가 2보다 엄격하게 큰 레코드만 처리합니다.prefix=$1+2
awk의 "접두사" 내부 변수를 정의합니다. 접두사$1
+ 2 와 수치적으로 동일하게 만듭니다 .printf("my_format",var1,var2,...)
줄 바꿈으로 구분된 인쇄 형식 지정 명령입니다. 형식 지정에는%0.2d
변수 "접두사"를awk
두 자리 숫자로 인쇄하고 필요한 경우 0을 채우는 작업이 포함됩니다. 출력은 다음과 같습니다
mv -f 05_file_name.log 07_file_name.log
mv -f 05_file_name.txt 07_file_name.txt
mv -f 04_file_name.log 06_file_name.log
mv -f 04_file_name.txt 06_file_name.txt
mv -f 03_file_name.log 05_file_name.log
mv -f 03_file_name.txt 05_file_name.txt
- 정렬된 출력을 다른 파일(두 번째 프로세스 교체)로 처리하고 명령을 실행하도록 합니다
mv -f ...
.
왜 재사용하는지 궁금하시다면인바운드 또는 아웃바운드 프로세스 교체(POSIX가 아닙니다!) in bash
이 유리합니다.이것예를 들어.
최종 참고사항:
위의 코드 줄에 런타임 매개변수를 포함하고 이를 실행 가능한 셸 스크립트에 캡슐화하는 것은 쉽습니다. 정의 VAR1
하고 VAR2
할당하는 프로세스부터 시작하세요 awk
.
$ source <(awk -v VAR1=2 -v VAR2=2 'BEGIN{FS="_"} $1>VAR1 {prefix=$1+VAR2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}' <(ls -r -1 *_file_name.{log,txt}))
실행 가능한 스크립트에서 script.sh
:
$ cat script.sh
#!/usr/bin/bash
if [ "$#" -eq 2 ] ; then
source <(awk -v VAR1=$1 -v VAR2=$2 'BEGIN{FS="_"} $1>VAR1 {prefix=$1+VAR2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}'
<(ls -r -1 *_file_name.{log,txt})
)
exit 0
else
echo " Usage: script.sh VAR1 VAR2.\n Abort execution (exit code 1)."
exit 1
fi
여기서 VAR1
및 VAR2
OP에 정의된 의미가 있습니다. 프로덕션 환경에서 이 스크립트를 사용해야 하는 경우 입력 파일 및 변수의 값이 항상 예상되는지 확인하기 위해 많은 검사와 안전 장치를 추가하는 것이 좋습니다.
for
@MarceloCastro의 스크립트는 훌륭하지만 가능하면 피하는 경향이 있는 루프를 기반으로 합니다 . for
루프는 느린 경향이 있습니다. 루프를 작업하면 이를 알 수 있습니다.큰파일 수.
답변3
나는 당신의 목표에 맞게 이 스크립트를 만들었습니다.
for files in *.extensions
do
num=$(echo "$files" | awk '{print $1}' | cut -c1-2)
if [ $num -gt 2 ]; then
AS=$((num+2))
temp=$(echo "$files" | cut -c 3-)
mv $files 0$AS"$temp"
fi
done
답변4
그리고 zsh
:
$ autoload zmv
$ zmv -n -f '(<3->)(_*)(#qnOn)' '${(l:2::0:)$(($1+2))}$2'
mv -- 05_file_name.txt 07_file_name.txt
mv -- 05_file_name.log 07_file_name.log
mv -- 04_file_name.txt 06_file_name.txt
mv -- 04_file_name.log 06_file_name.log
mv -- 03_file_name.txt 05_file_name.txt
mv -- 03_file_name.log 05_file_name.log
그런 다음 실제로 이 작업을 수행하려면 제거 -n
(모의 실행을 위해)하십시오.
zmv pattern replacement
:zmv
강력한 zsh glob 및 Spread 연산자를 활용하여 복잡한 파일 이름 바꾸기를 수행하는 자동 로드 가능 기능입니다.<x-y>
10진수 x와 y를 일치시킵니다.(#q...)
글로벌 예선nOn
: ame의n
숫자 rdero
(대문자 O로 반전)n
. 따라서 숫자를 늘리고 있으므로05...
필요에 따라 그보다 먼저 올 것입니다.04...
${(l:n::padding:)expansion}
:l
패드 길이 연장N사용충전재. 따라서${(l:2::0:)}
사용시 길이는 0~2로 유지한다.$(($1+2))
, 첫 번째 캡처된 그룹은 2씩 증가합니다.$2
:두 번째 캡처 그룹: 선행 숫자 뒤에 오는 내용입니다.