특정 패턴의 파일 복사

특정 패턴의 파일 복사

한 위치에서 다른 위치로 파일을 복사하려고 합니다. 다음은 몇 가지 예입니다.

aaa_bbb_ccc_ddd_cost_code_20140330.gz
aaa_bbb_ccc_ddd_revenue_zone_20140329.gz
aaa_bbb_ccc_ddd_benefit_extract_20140330.csv.gz
aaa_bbb_ccc_ddd_profit_zone_20150509.csv.gz
aaa_bbb_ccc_ddd_loss_zone_20140330.csv
aaa_bbb_ccc_ddd_username.csv.gz

위 목록에서 복사해야 하는 파일은 다음 형식이어야 합니다.

aaa_bbb_ccc_ddd_cost[or]revenue[or]benefit[or]profit[or]loss_yyyymmdd.csv.gz

이는 파일을 의미합니다.

aaa_bbb_ccc_ddd_loss_zone_20140330.csv
aaa_bbb_ccc_ddd_username.csv.gz

복사하면 안 됩니다.

또한 변수에 할당해야 하는데 다음과 같이 시도하고 있지만 작동하지 않는 것 같습니다.

FILENAME="egrep 'aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit)_code_[0-9]{8}.csv.gz'"

변수에 할당하려는 이유는 나중에 다음을 수행하기 위해 코드에서 이를 사용해야 하기 때문입니다.

SOURCE_DIR="/temp"
DESTN_DIR="/output"
FILENAME=`egrep 'aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit)_code_[0-9]{8}.csv.gz'`
echo "FILENAME is:" $FILENAME
for SAMPLE_FILE in $(ls "$SOURCE_DIR/$FILENAME")
do
cp $SAMPLE_FILE $DESTN_DIR
done

이것을 달성하는 다른 방법이 있습니까?

답변1

Use find-exec해당 옵션(여기서는 GNU를 조건 find자로 사용 -regex):

find . -regextype posix-egrep -regex '.*/aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit|loss)_[[:alpha:]]+_[0-9]+\.csv\.gz' -exec mv {} "$DESTN_DIR" \;

노트:

  • find .find현재 디렉터리부터 검색할 파일을 알려줍니다 .

  • 기본적으로 GNU는 findemacs 스타일 정규식을 사용합니다. 저는 을 선호 -regextype posix-egrep하지만, 지원되는 익숙한 스타일로 전환할 수 있습니다.

  • 정규식을 사용하여 파일을 선택합니다. -regex '.*/aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit|loss)_[[:alpha:]]+_[0-9]+\.csv\.gz'표준 접두사 aaa_bbb_ccc_ddd_뒤에 지정된 단어 중 하나 (cost|revenue|benefit|profit|loss), 지정되지 않은 다른 단어, _[[:alpha:]]+날짜, _[0-9]+마지막으로 원하는 확장자가 옵니다 .csv.gz. 이를 미세 조정해야 할 수도 있습니다.

  • 발견된 모든 파일은 대상 디렉토리로 이동됩니다 -exec mv {} "$DESTN_DIR" \;. 일치하는 파일이 발견 되면 find이 명령을 실행하고 {}파일 이름을 바꿉니다. 이는 파일 이름에 공백, 줄 바꿈 또는 기타 읽을 수 없는 문자가 포함된 경우에도 작동합니다.

정규식을 사용하는 기본(emacs) 스타일

GNU 정규식의 기본 스타일에는 find그룹화 및 대체 연산자의 일부 이스케이프가 필요합니다.

find . -regex '.*/aaa_bbb_ccc_ddd_\(cost\|revenue\|benefit\|profit\|loss\)_[[:alpha:]]+_[0-9]+\.csv\.gz' -exec echo mv {} targetdir \;

애플 컴퓨터

Mac OSX 버전 find(매뉴얼 페이지는 여기에 있습니다)은 지원되지만 -regex지원되지는 않습니다 -regextype. 하지만 정규식 구문에 약간의 변경이 필요하더라도 놀라지 않을 것입니다.

IBM AIX 5

IBM AIX 버전의 매뉴얼 페이지 find는 다음과 같습니다.여기. 물론아니요지원하다 -regex.

답변2

그리고 zsh:

setopt extendedglob
source_dir="/temp"
destn_dir="/output"
pattern='aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit)_code_[0-9](#c8).csv.gz'
print -r "pattern is: $pattern"
cp -- $source_dir/$~pattern $destn_dir

ksh93 패턴은 다음과 같은 방식으로 표현될 수 있습니다.

aaa_bbb_ccc_ddd_@(cost|revenue|benefit|profit)_code_{8}(\d).csv.gz

그리고 ksh88:

aaa_bbb_ccc_ddd_@(cost|revenue|benefit|profit)_code_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv.gz

하지만, 그확장하다POSIX 호환성이 깨지는 것을 방지하기 위해 와일드카드는 변수 내에서 작동할 수 없습니다.

echo @(a)

이는 POSIX에 따른 잘못된 구문이므로 ksh새로운 glob 연산자로 만들 수 있습니다. 하지만:

x='@(a)'
echo $x

POSIX에서 지정한 것과 정확히 일치하며 현재 디렉터리에서 호출된 파일이 @(a)아닌 출력(IFS의 기본값 사용)을 의미합니다.aa

eval따라서 다음 을 사용해야 합니다.

pattern='aaa_bbb_ccc_ddd_@(cost|revenue|benefit|profit)_code_{8}([0-9]).csv.gz'
print -r "pattern is: $pattern"
eval 'cp -- "$source_dir"/'"$pattern"' "$destn_dir"'

답변3

이 작업은 한 줄로 수행할 수 있습니다.

find /temp -maxdepth 1 -type f | \
 grep -P 'aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit)_.*[0-9]{8}' | \
 xargs cp -t /output
  • find하위 폴더가 없는 폴더의 내용을 나열합니다.
  • grep당신의 파일 이름
  • cp대상 디렉터리( -t) 에 복사 합니다 .

질문이 100% 명확하지 않으므로 정규식을 조정하면 됩니다. 어떤 문서에는 그런 내용이 있고 .csv.gz, 어떤 문서에는 있고 .csv, 어떤 문서에는 있습니다 .gz.

답변4

모든 최신 쉘은 기본 glob 구문을 사용하지 않고 다음과 같이 원하는 것을 직접 지원합니다.

cp aaa_bbb_ccc_ddd_{cost,revenue,benefit,profit,loss}_[0-9]*.csv.gz destination_dir

이는 5개의 인수로 확장되며, 각 인수는 다음 형식의 구체입니다...._keyword_<digits>...

두 번째 질문에 답하기 위해 각 변수를 차례로 변수에 할당하는 방법은 다음과 같습니다.

for FNAME in aaa_bbb_ccc_ddd_{cost,revenue,benefit,profit,loss}_[0-9]*.csv.gz
do
    echo $FNAME
    if [ -e $FNAME ]
    then
        cp $FNAME <destination>
    fi
done

존재 확인( if [ -e $FNAME ])은 5개의 글로브 중 하나라도 일치하지 않는 경우 글로브를 그대로 유지하고 오류 메시지를 받기 때문에 발생합니다.

관련 정보