Unix 폴더의 여러 파일 이름에서 여러 문자 바꾸기

Unix 폴더의 여러 파일 이름에서 여러 문자 바꾸기

내 Unix 폴더에 /home/TRANS라는 파일이 여러 개 있습니다.

이 폴더는 매달 파일을 받습니다. 파일 이름은 다음과 같습니다.

  • ENCD_213_E-DM_CCA_ID3490_A01.txt
  • ENCD_213_E-DM_CCA_ID33120_A01.txt
  • ENCD_213_E-DM_CCA_IDP3664_A01.txt
  • ENCD_213_E-DM_CCA_ID3327_A01.txt
  • ENACT_215_E_DM_CCA_IDA33320_25OCT2017.csv
  • ENACT_215_E_DM_CCA_IDA31116_25OCT2017.csv

이름을 바꾼 후 최종 출력은 다음과 같습니다.

  • id3490.txt
  • id33120.txt
  • idp3664.txt
  • id3327.txt
  • ida33320.csv
  • ida31116.csv

따라서 기본적으로 TRANS 폴더의 모든 파일 이름에서 다음 문자열을 바꾸고 최종 출력 파일 이름을 소문자로 만들고 싶습니다.

  • ENCD_213_E-DM_CCA_
  • _A01
  • ENACT_215_E_DM_CCA_
  • _2017년 10월 25일

한 줄 명령이나 쉘 스크립트에서 이 작업을 어떻게 수행할 수 있습니까? 여러 질문을 확인했지만 소문자로 변경하는 것 외에 여러 문자를 대체할 수 없습니다. 저는 Unix를 처음 접했기 때문에 여러분의 도움이 필요합니다.

답변1

이를 수행하는 방법에는 여러 가지가 있습니다. 귀하의 예에 적합한 명령은 다음과 같습니다.

for oldname in *; do
    newname="$(echo "${oldname}" | grep -Po 'ID\w?\d+' | tr A-Z a-z).txt" \
    && mv -i "${oldname}" "${newname}";
done

grep이 예 에서는 지원하지 않는 것으로 보이는 Perl 호환 정규식을 사용합니다 . 다음은 기본 정규식을 사용하는 대안입니다.

for oldname in *; do
    newname="$(echo "${oldname}" | grep -o 'ID[A-Z]\?[0-9]\+' | tr A-Z a-z).txt" \
    && mv -i "${oldname}" "${newname}";
done

아래는 좀 더 자세한 설명입니다.


이 표현은 다음 for oldname in *을 사용합니다.와일드카드 패턴/와일드카드현재 디렉터리의 파일을 반복하고 각 이름을 oldname변수에 저장합니다. 이를 테스트하려면 다음 명령을 실행할 수 있습니다.

for oldname in *; do echo "${oldname}"; done

grep그런 다음 유지하려는 파일 이름 부분을 추출하는 데 사용합니다 . 옵션 -P플래그는 grepPerl 호환 정규식을 사용하도록 지시하고(이 경우에는 실제로 필요하지 않음) 플래그 는 전체 문자열을 인쇄하는 대신 일치하는 하위 문자열만 추출 -o하도록 지시합니다 . grep패턴 \w?은 옵션의 단일 문자("단어" 문자)와 일치하고 \d+패턴은 하나 이상의 숫자와 일치합니다. 다음과 같이 정규식을 테스트할 수 있습니다.

for oldname in *; do echo "${oldname}" | grep -Po 'ID\w?\d+'; done

그런 다음 tr다음을 사용하여 대문자를 소문자로 변환합니다.

for oldname in *; do echo "${oldname}" | grep -Po 'ID\w?\d+' | tr A-Z a-z; done

다음 단계는 사용하는 것입니다.명령 대체이 문자열을 변수에 할당하고 결과를 인쇄합니다.

for oldname in *; do
    newname="$(echo "${oldname}" | grep -Po 'ID\w?\d+' | tr A-Z a-z)" && echo "${newname}"
done

그런 다음 ".txt" 파일 확장자를 추가합니다.

for oldname in *; do
    newname="$(echo "${oldname}" | grep -Po 'ID\w?\d+' | tr A-Z a-z).txt" && echo "${newname}"
done

이 명령을 온전성 검사로 실행하여 예상한 결과를 얻을 수 있는지 확인할 수 있습니다. 만족스러우면 echo해당 명령을 다음으로 바꿉니다 mv.

for oldname in *; do
    newname="$(echo "${oldname}" | grep -Po 'ID\w?\d+' | tr A-Z a-z).txt" \
    && mv -i "${oldname}" "${newname}";
done

답변2

find+bash해결책:

find . -type f -regextype posix-egrep \
    -regex ".*EN(ACT|CD)_[0-9]+_E(-|_)DM_CCA_.+[0-9]\.(txt|csv)$" -exec bash -c \
    'fn=${0##*/}; dir_n="${0%/*}/"; 
    [[ "$fn" =~ .*_(ID[^_]+)_.*\.(txt|csv)$ ]]; 
    mv "$0" "$dir_n${BASH_REMATCH[1],,}.${BASH_REMATCH[2]}"; ' {} \;

답변3

파일 이름 조작의 경우 bash 매개변수 확장이 좋습니다. 바라보다이것좋은 개요를 얻으려면.

기본적으로 파일의 ID 부분을 유지하려고 하므로 다음과 같이 할 수 있습니다.

#!/bin/bash

for f in *csv *txt; do
   ext="${f##*.}"

   if [[ $f =~ ID[[:alnum:]]+ ]]; then
      mv "$f" "${BASH_REMATCH,,}.${ext}"
   fi

done

exit

이는 각 csv 및 txt 파일을 반복하고 PE를 사용하여 확장자를 가져옵니다. 그런 다음 bash 정규식 일치 연산자를 사용하여 =~파일 이름이 패턴과 일치하는지 확인하세요. 그렇다면 bash는 $BASH_REMATCH정규식이 일치하는 내용으로 이를 채울 것입니다. 그런 다음 파일은 원래 확장자가 추가된 해당 일치 항목의 소문자 버전으로 이동됩니다. 모든 샘플 파일을 생성하고 예상한 결과를 얻었습니다.

관련 정보