저는 일련의 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_FILEMASK
FILEMASK
변수 f
및 extractDir
포함 파일 이름이 있으므로 큰따옴표를 유지해야 합니다.
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
파일 누락에 대한 불만이 없습니다.