Bash: 특정 패턴의 파일 이동

Bash: 특정 패턴의 파일 이동

저는 일련의 zip 파일을 반복하여 추출하고 특정 파일 이름 패턴과 일치하는 파일만 다른 폴더로 이동하는 스크립트를 작성했습니다.

스크립트:

#!/bin/bash

ARCHIVE_FILEMASK="????-??-??_E_MDT_0_0.7z"
FILEMASK="?????????_?????_A_?_????????????????-?????????"
extractDir=/path/to/dir
dest=/path/to/dest

for f in ${ARCHIVE_FILEMASK}
do
    7z e -aoa -o"${extractDir}" "$f"
    if [ $? != 0 ]
    then
        mv "${extractDir}/${FILEMASK}".xml "$dest"
    fi
done

스크립트를 실행하는 동안 오류가 발생했습니다:

mv: cannot stat `/path/to/dir/?????????_?????_A_?_????????????????-?????????.xml': No such file or directory

nullglob과 extglob을 열려고 시도했지만 도움이 되지 않았습니다. 쉘에서 직접 명령을 실행하면 정상적으로 실행됩니다. 비슷한 질문이 있는 다른 게시물의 답변도 도움이 되지 않았습니다.

편집하다: Paweł Rumian이 디렉토리 이름의 공백에 문제가 있을 수 있다고 언급한 후 AVJ의 프롬프트를 시도하고 명령 set +x앞에 mv.

결과 :

+ mv '/path/to/dir/????????????????????????_A_?_????????????????????-???????? ??.xml'/경로/to/dest

그래서 이제 작은따옴표를 제거해야 합니다. 어떻게 해야할지 아시나요?

답변1

일반적으로 변수 확장 주위에 큰따옴표를 사용하는 것이 좋습니다. $foo바깥쪽 따옴표는 "값을 가져와서 foo공백으로 나누고 각 결과 단어가 하나 이상의 파일과 일치하면 이를 와일드카드 패턴으로 확장"을 의미하기 때문입니다. foo특히 변수에 파일 이름이 포함된 경우 원하는 값 입니다 . 그러나 여기서는 실제로 파일 이름을 사용할 때 확장하려고 foo하므로 따옴표로 묶어서 사용하면 안 됩니다. 분리된 패턴 목록; 이 변수의 값에 공백이 없기 때문에 여기서는 아무런 차이가 없습니다."$foo"ARCHIVE_FILEMASKFILEMASK

변수 fextractDir포함 파일 이름이 있으므로 큰따옴표를 유지해야 합니다.

for f in ${ARCHIVE_FILEMASK}
do
    if 7z e -aoa -o"${extractDir}" "$f"; then
        mv "${extractDir}/"${FILEMASK}.xml "$dest"
    fi
done

Bash를 사용하고 있으므로 와일드카드 패턴이 어떤 파일과도 일치하지 않으면 shopt -s nullglob와일드카드 패턴을 빈 목록으로 확장하도록 호출할 수 있습니다. 명령에 소스 파일을 전달하지 않으면 "${extractDir}/"${FILEMASK}.xml명령 mv은 파일 누락에 대해 불평합니다. 일치하는 항목이 하나 이상 있는 경우에만 호출하여 문제를 해결할 수 있습니다.

shopt -s nullglob
for f in ${ARCHIVE_FILEMASK}
do
    if 7z e -aoa -o"${extractDir}" "$f"; then
        matches=("${extractDir}/"${FILEMASK}.xml)
        if ((${#matches[@]})); then
            mv "${matches[@]}" "$dest"
        fi
    fi
done

1 이상은 일반적으로 표시된 것과 같습니다 IFS.

답변2

해결책은 큰따옴표를 제거하는 것입니다. 이제 이동 명령은 다음과 같습니다.

mv ${extractDir}/${FILEMASK}.xml "$dest"

답변3

이는 mv 명령이 소스 파일을 찾을 수 없기 때문입니다. 소스 파일 이름에는 특수 문자나 기타 내용이 포함될 수 있습니다.

배치하여 스크립트를 실행합니다.세트-xmv 명령 앞뒤에 +x를 설정합니다.

스크립트 실행 중에 실행되는 정확한 명령이 표시됩니다. 쉘에서 직접 명령을 실행하여 이를 확인하십시오.

답변4

.7z 파일에 정확히 동일한 파일 이름의 여러 인스턴스가 포함되어 있습니까? 내 생각에는 그렇지 않은 것 같습니다. 모두 동일한 "$dest" 디렉토리로 옮겼기 때문입니다.

mv이 경우 명령을 루프 외부에 두는 것이 더 낫습니다 . 부분적으로는 mv전체 명령을 하나만 실행하기 때문입니다( mv.7z 파일당 하나가 아닌). 하지만 대부분 파일이 하나 이상 있을 가능성이 높기 때문입니다. 당신의 패턴으로. 그리고 변수 주위에 큰따옴표를 유지할 수 있습니다. 이는 파일 이름에 쉘 또는 글로브 중요한 문자가 포함되어 있는 경우 더 안전합니다.

단일 명령으로 너무 많은 파일을 추출하는 경우 다음과 같이 mv를 사용할 수 있습니다 find.

find "$extractDir" -name "$FILEMASK.xml" -exec mv {} "$dest/" +

어쨌든 사용하는 것이 더 좋습니다 find. 얼마나 많은 파일이 추출될지 알 수 없으므로 방어 프로그래밍에 유용합니다. 또한 일치하는 파일이 발견되지 않으면 아무 작업도 수행하지 않는다는 장점이 있으므로 mv파일 누락에 대한 불만이 없습니다.

관련 정보