다음은 이름을 바꿔야 하는 파일의 작은 샘플입니다.
ID_EDMSCP_20160815.txt.pgp
ID_EDMSCP_20160816.txt.pgp
ID_EDMSCP_20160817.txt.pgp
ID_EDMSCP_20160818.txt.pgp
다른 사람의 질문을 바탕으로 스크립트를 만들었는데 다음과 같습니다.
for file in ID_EDMSCP_*.txt.pgp
do
mv -i "${file}" "${file/-ID-/-SUBMIT_GO_ID-}"
done
그러나 다음 메시지가 나타납니다.
mv: `ID_EDMSCP_20160815.txt.pgp' and `ID_EDMSCP_20160815.txt.pgp' are the same file
그리고 아무것도 이름이 바뀌지 않았습니다. 내가 뭐 놓친 거 없니?
답변1
mv -i "${file}" "${file/-ID-/-SUBMIT_GO_ID-}"
-ID-
이 문자열 대체는 소스 파일 이름에 나타나지 않는 대체를 지시합니다 . 내 생각엔 당신이 이렇게 말하려는 것 같아요.
mv -i "${file}" "${file/ID_/SUBMIT_GO_ID_}"
또 다른 문제는 이것이 ksh93
Bash와 Zsh에서도 사용할 수 있는 기능이라는 것입니다.순수 POSIX 쉘이 아님. #!/bin/sh
스크립트 상단에서 사용 하면 POSIX 쉘 또는 POSIX 이전 Bourne 쉘 인터프리터에서 실행됩니다.일부 시스템에서는, 이것은 이해되지 않을 것입니다.
고급 셸의 비표준 기능에 액세스할 수 없는 경우 다양한 대안이 있습니다.
sed
이 스크립트를 모든 Unix 유형 시스템으로 이식해야 하는 경우 sed
대체 스크립트로 전환할 수 있습니다.
mv -i "$file" "$(echo $file | sed -e 's/^ID_/SUBMIT_GO_ID_/')"
스타일 명령 보간법을 사용하기 때문에 $()
최소한 POSIX 쉘이 필요하지만, 모든 곳에서 높은 수준의 쉘을 기대하는 것보다 "생각해내기"가 더 쉽습니다.
스크립트가 모든 Bourne 유형 셸에서 실행되어야 하는 경우 백틱 스타일 명령 보간으로 전환할 수 있습니다. 파일 이름에 공백이 포함되어 있으면 올바르게 수행하기 어려울 수 있지만 게시한 예에 따르면 다음과 같은 것 같습니다. 사실이 아니다. 따라서 귀하의 목적에 따라 이는 이전 옵션과 동일해야 합니다.
mv -i "$file" `echo $file | sed -e s/^ID_/SUBMIT_GO_ID_/`
밀리미터파
또 다른 옵션은 설치하는 것입니다mmv
, 이 프로그램은 내가 아는 Unix 유형 시스템에는 설치되지 않지만 일반적으로 표준 패키지 저장소에 패키지되어 있습니다. 를 사용하면 mmv
전체 쉘 스크립트 루프를 다음으로 바꿀 수 있습니다.
$ mmv 'ID_*' 'SUBMIT_GO_ID_#1'
모든 이름 바꾸기 요구는 지원되지 않으므로 -i
플래그 가 없습니다 . mmv
그러나 계획된 모든 이름 바꾸기를 사전 확인하고 작업을 시작하기 전에 문제를 감지하려고 시도하므로 아마도 귀하의 목적에 충분히 근접할 것입니다.
이름을 바꿔라
또 다른 옵션은 rename
최소한 세 가지 변형으로 존재하는 명령입니다. 가지다둘 포크같은 이름의 Larry Wall의 Perl 스크립트. 그 중 하나는 Perl 배포판의 일부로 시스템에 이미 설치되어 있을 수 있습니다. 이후util-linux
변형은 일반적으로 이 버전 대신 Linux 시스템에 설치되거나 그 옆에 설치됩니다. 둘 다 설치된 경우 prename
충돌을 피하기 위해 Perl 기반 버전을 호출할 수 있습니다 .
Perl 기반의 주요 장점은 다음을 사용할 수 있다는 것입니다.펄 정규식mmv
이는 지원되는 glob 표현식이나 지원되는 POSIX 정규 표현식보다 더 강력합니다 sed
. 그러나 이 특정 예에서는 작업이 간단하기 때문에 중요하지 않습니다.
$ rename '^ID_' SUBMIT_GO_ID_ ID_EDMSCP_*.txt.pgp
이 util-linux
버전은 첫 번째 인수를 "표현식"이라고 부르지만 POSIX 정규 표현식이나 Perl 정규 표현식이 아니기 때문에 훨씬 약합니다. 이는 전역 표현식도 아니며 단지 리터럴 문자열일 뿐입니다. 그러나 위에서 언급했듯이 이 특별한 경우에는 이 제한이 실제로 우리를 방해하지 않습니다.
$ rename ID_ SUBMIT_GO_ID_ ID_EDMSCP_*.txt.pgp
mmv
와 마찬가지로 rename
이 -i
플래그는 지원되지 않습니다.
평범한 오래된 베른 껍질
요약하자면, 입력 패턴이 출력 패턴의 끝에 나타나므로 특정 사례에서는 더 간단한 솔루션이 가능하므로 이식 가능한 Bourne 쉘 구문을 사용하여 모든 작업을 수행할 수 있습니다.
for file in ID_EDMSCP_*.txt.pgp
do
mv -i "$file" SUBMIT_GO_"$file"
done
쉘 언어의 내부 메커니즘이 항상 충분하지 않기 때문에 종종 필요한 복잡한 대안을 위에 남겨두었습니다.
답변2
이 시도:
for file in ID_EDMSCP_*.txt.pgp
do
mv -i "${file}" SUBMIT_GO_"${file}"
done
답변3
Linux에서는 다음을 사용할 수 있습니다.rename
주문하다. 매우 제한적이지만 이 간단한 사용 사례에는 충분합니다. 첫 번째 부분 문자열을 다른 문자열로 바꿉니다.
rename ID SUBMIT_GO_ID ID_EDMSCP_*.txt.pgp
Debian 및 그 파생 제품(Ubuntu, Mint 등)에서는 명령이 호출됩니다 rename.ul
. 이러한 배포판의 명령은 rename
호환되지 않는 구문을 사용하는 다른 명령입니다 .prename
. 이 명령을 사용하면 다음을 수행할 수 있습니다.
prename 's/ID/SUBMIT_GO_ID/' ID_EDMSCP_*.txt.pgp