쉘을 통한 확장

쉘을 통한 확장

여러 하위 디렉터리가 있는 디렉터리가 있습니다. 가지다압축파일에 대한 질문여기에는 내 필요에 맞게 약간 수정한 답변이 포함되어 있습니다.

for i in */; do zip "zips/${i%/}.zip" "$i*.csv"; done

그런데 이상한 문제에 부딪혔습니다. 존재하지 않는 첫 번째 폴더 세트의 경우 zips/<name>.zip다음 오류가 발생합니다.

zip error: Nothing to do! (zips/2014-10.zip)
        zip warning: name not matched: 2014-11/*.csv

하지만그냥 echozip 명령문을 사용하는 경우:

for i in */; do echo zip "zips/${i%/}.zip" "$i*.csv"; done

그런 다음 echo 명령( zip zips/2014-10.zip 2014-10/*.csv)을 실행했는데 제대로 작동하고 폴더가 압축되었습니다. 흥미로운 부분은 원래 명령의 후속 실행입니다.~ 할 것이다처음에는 작동하지 않았던 폴더를 압축하는 것이 실제로 가능합니다!

이 동작을 직접 테스트하려면 다음을 수행하세요.

cd /tmp
mkdir -p 2016-01 2016-02 2016-03 zips
for i in 2*/; do touch "$i"/one.csv; done
for i in 2*/; do touch "$i"/two.csv; done
zip zips/2016-03.zip 2016-03/*.csv
for i in 2*/; do echo zip "zips/${i%/}.zip" "$i*.csv"; done
for i in 2*/; do zip "zips/${i%/}.zip" "$i*.csv"; done

echo가 다음 명령문을 인쇄하는 것을 볼 수 있습니다.

zip zips/2016-01.zip 2016-01/*.csv
zip zips/2016-02.zip 2016-02/*.csv
zip zips/2016-03.zip 2016-03/*.csv

그러나 실제 zip 명령은 다음을 알려줍니다.

        zip warning: name not matched: 2016-01/*.csv

zip error: Nothing to do! (zips/2016-01.zip)
        zip warning: name not matched: 2016-02/*.csv

zip error: Nothing to do! (zips/2016-02.zip)
updating: 2016-03/one.csv (stored 0%)
updating: 2016-03/two.csv (stored 0%)

.csv따라서 실제로는 zip 파일이 들어 있는 s로 zip 파일을 업데이트하지만아니요zip 파일을 생성할 때. zip 명령 중 하나를 복사하는 경우:

$ zip zips/2016-02.zip 2016-02/*.csv
adding: 2016-02/one.csv (stored 0%)
adding: 2016-02/two.csv (stored 0%)

그런 다음 zip-all-the-things를 다시 실행하십시오.

for i in 2*/; do zip "zips/${i%/}.zip" "$i*.csv"; done

2016-02및 에 대해 업데이트된 것을 볼 수 있습니다 2016-03. 이것은 내 결과입니다 tree.

.
├── 2016-01
│   ├── one.csv
│   └── two.csv
├── 2016-02
│   ├── one.csv
│   └── two.csv
├── 2016-03
│   ├── one.csv
│   └── two.csv
└── zips
    ├── 2016-02.zip
    └── 2016-03.zip

또한 놀랍게도 이것은 잘 작동합니다.

zsh -c "$(for i in 2*/; do echo zip "zips/${i%/}.zip" "$i*.csv"; done)"

내가 여기서 뭘 잘못하고 있는 걸까? (참고로 저는 bash 대신 zsh를 사용하고 있습니다. 차이가 있다면)

답변1

쉘을 통한 확장

주변 인용문이 "$i*.csv"다릅니다. 따옴표를 사용하면 셸은 문자열을 "2014-11/*.csv"로 확장합니다. 정확한 파일이 존재하지 않으며 zip오류가 보고됩니다. 따옴표가 없으면 *확장도 수행되며(파일 이름 확장/"globbing"을 통해) 결과 zip명령은 각각 별도의 인수로 일치하는 파일의 전체 목록입니다. 다음을 사용하여 루프 내에서 두 번째 동작을 얻을 수 있습니다 for.

for i in */ ; do zip "zips/${i%/}.zip" "$i"*.csv ; done

zip 확장을 통해

zip와일드카드를 자체적으로 확장하는 것도 가능하지만 모든 경우에 그런 것은 아닙니다. ~에서지퍼 수동:

이것압축프로그램은 다음의 이름에 대해 동일한 일치를 수행할 수 있습니다.압축아카이브가 수정되었거나,-엑스(제외) 또는-나(include) 옵션은 작업할 파일 목록에 백슬래시나 따옴표를 사용하여 이름 확장을 수행하지 않도록 쉘에 지시합니다.

아카이브를 성공적으로 생성한 후 원래 명령은 zip기존 아카이브의 내용과 와일드카드를 일치시키려고 시도하므로 후속 시도에서 작동합니다. 그것들은 거기에 존재했고 여전히 파일 시스템에 존재하므로 결국 updating:.

zip와일드카드를 얻으려면만들다-r(recurse) 옵션을 사용하여 요청된 디렉터리로 재귀적으로 보관 하고 -i패턴과 일치하는 파일로 제한(포함)합니다.

 for i in */ ; do zip -r "zips/${i%/}.zip" "$i" -i '*.csv' ; done

관련 정보