log_<date>.txt
중첩된 디렉토리에 흩어져 있는 동일한 명명법을 공유하는 파일이 있습니다 root
. 파일이 생성된 날짜 는 <date>
YYYYmmddHHMM 형식입니다. 코드 호환성 문제로 인해 모든 파일의 이름을 다음으로 바꾸고 싶습니다.<date>_log.txt
표현식 을 캡처해야 한다는 것을 알고 있지만 <date>
bash에서 어떻게 캡처합니까? 또한 중첩된 디렉터리에서는 어떻게 수행합니까?
답변1
쉘 변수에 이러한 파일 중 하나의 이름이 있다고 가정해 보겠습니다 name
. log_
그런 다음 변수 값에서 비트를 제거하는 작업 은 로 수행되고 ${name#log_}
, .txt
비트 제거는 으로 수행됩니다 ${name%.txt}
. 남은 것은 날짜이며, 그것이 어떤 형식으로 되어 있는지는 본질적으로 흥미롭지 않습니다. 제거된 값을 가져와서 _log_.txt
끝에 추가하여 새 이름을 만드는 것은 쉽습니다 .
단일 디렉토리의 파일에 대해 이를 수행하려면 루프를 사용하십시오. 이제 변수 값의 시작 부분에 있는 디렉터리 이름도 제거해야 합니다.
shopt -s nullglob
for name in root/log_*.txt; do
newname=root/${name#root/log_} # remove prefix, add root/ back
newname=${newname%.txt}_log.txt # remove suffix, add _log.txt back
printf 'Would move "%s" to "%s"\n' "$name" "$newname"
# mv -i "$name" "$newname"
done
안전을 위해 실제 명령을 주석 처리했습니다 mv
. 먼저 어떤 일이 발생하는지 확인하려면 한 번 테스트 실행해야 합니다.
shell 옵션은 쉘을 nullglob
만듭니다.bash
제거하다확장되지 않은 채로 두는 것이 아니라 비교할 수 없는 패턴을 만듭니다. 이는 log_*.txt
해당 디렉토리에 파일이 없으면 루프가 전혀 실행되지 않음을 의미합니다 .
이는 현재 디렉터리(현재 디렉터리 포함) 아래의 모든 파일에 반복적으로 적용할 수 있습니다.다소간우리가 반복하는 패턴을 수정하면 됩니다.
shopt -s globstar nullglob
for name in ./**/log_*.txt; do
dirpath=${name%/*} # get path of directory
newname=$dirpath/${name#$dirpath/log_} # remove prefix, add directory path back
newname=${newname%.txt}_log.txt # remove suffix, add _log.txt back
printf 'Would move "%s" to "%s"\n' "$name" "$newname"
# mv -i "$name" "$newname"
done
다른 변경 사항에는 하위 디렉터리를 일치시키는 데 globstar
사용할 수 있는 셸 옵션 활성화가 포함됩니다. **
또한 새 이름 앞에 추가할 수 있는 디렉토리 경로를 선택합니다.
find
루프에 대한 입력을 생성하는 데 사용할 수도 있습니다 .
find . -type f -name 'log_*.txt' -exec sh -c '
for name do
dirpath=${name%/*} # get path of directory
newname=$dirpath/${name#$dirpath/log_} # remove prefix, add directory path back
newname=${newname%.txt}_log.txt # remove suffix, add _log.txt back
printf "Would move \"%s\" to \"%s\"\n" "$name" "$newname"
# mv -i "$name" "$newname"
done' sh {} +
이는 현재 디렉터리 또는 그 아래에서 이름이 일치하는 모든 일반 파일을 찾은 다음 위의 두 번째 변형의 루프와 기본적으로 동일한 작업을 수행하는 log_*.txt
인라인 스크립트에 일괄적으로 전달합니다 .sh -c
답변2
zsh
가장 좋은 방법은 's 와 같은 배치 파일 이름 바꾸기 도구나 다음의 Perl 기반 변형 중 하나를 사용하는 zmv
것 mmv
입니다 rename
.
zsh << 'EOF'
autoload zmv
zmv 'log_(*).txt' '${1}_log.txt'
EOF
또는
prename 's/log_(.*)\.txt/${1}_log.txt/' log*.txt