특정 확장자를 가진 모든 파일을 gzip


11

파일 확장자가 .css, .html 또는 .js 인 우분투의 모든 파일을 압축하려고합니다. 최상위 디렉토리와 모든 하위 디렉토리에 있습니다. 원본 파일을 유지하고 이미 존재하는 경우 .gz 파일을 덮어 쓰고 싶습니다.

따라서 n 개의 파일이 있으면이 n 파일을 유지하고 추가 n 개의 아카이브 파일을 만들고 싶습니다. 하나만이 아닙니다.

내 시도는 다음과 같은 스크립트를 실행하는 것입니다.

gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension

먼저 gzip으로 압축하려는 각 파일 확장자마다 해당 스크립트에 한 줄이 필요합니다. 괜찮지 만 더 좋은 방법을 찾고 싶습니다.

두 번째로 중요한 : 작동하지 않습니다. -r이 작업을 수행해야하지만 서브 디렉토리는 변경되지 않습니다. gzip 파일은 최상위 디렉토리에만 작성됩니다.

내가 여기서 무엇을 놓치고 있습니까?

Btw : 다음은 자세한 출력의 버그입니다. -k 및 -v 옵션을 사용하는 경우

-k, --keep        keep (don't delete) input files
-v, --verbose     verbose mode

"바꾸기"는 원래 파일이 교체 후에 존재하지 않음을 의미하지만 자세한 출력은 파일을 교체한다고 말합니다. 어쨌든 THis는 출력물입니다.

$ ls
  index.html      subdir1  testfile      testfile.css.gz
  javaclass.java  subdir2  testfile.css
$ gzip -fkv *.css
  testfile.css:   6.6% -- replaced with testfile.css.gz
$ ls
  index.html      subdir1  testfile      testfile.css.gz
  javaclass.java  subdir2  testfile.css

1
-r설계된대로 작동합니다. 에서 남자 GZIP : 디렉토리 구조 반복적으로 여행. 명령 행에 지정된 파일 이름이 directory 인 경우 gzip 은 디렉토리 로 내려 가서 찾은 모든 파일을 압축합니다 (또는 gunzip의 경우 압축 해제). (강조 광산)
Dennis

확인. 따라서 -r은 이름이 XYZ.css 인 디렉토리를 입력합니다. 그런 다음 재귀는 예상대로 설계되지 않았습니다.
Sadik

답변:


7

for 루프를 사용하여 모든 파일을 찾은 다음 압축 할 수 있습니다.

for i in `find | grep -E "\.css$|\.html$"`; do gzip "$i" ; done

감사합니다! 하지만 -r옵션이없는 작업을 수행 -k하고 -fI는 다음과 같이 사용할 수 있도록 노력하고 있습니다 : 난에 대한 find | grep -E "\.css$|\.html$"; gzip -vkf "$ i"수행; done`
Sadik

@Sadik : 조심하세요! 파일 이름에 공백이 있으면이 방법이 작동하지 않습니다.
Dennis

왜 그렇지 않은지 설명해 주시겠습니까?
Sadik

1
@Sadik : `...`목록이 아닌 문자열을 제공합니다. for내부 필드 구분 기호 ( $IFS)를 사용하여 해당 문자열을 분할 할 위치를 결정합니다. 기본적으로 줄 바꿈, 탭 및 공백으로 분할되므로이라는 파일이 있으면 new style.css명령 gzip newgzip style.css실행됩니다.
Dennis

1
@Sadik, Dennis가 맞습니다 . 루프 export IFS=$'\n'바로 전에 실행할 수있는 빠른 해결 방법 for입니다.
mndo

14

나는 사용할 것이다

find /path/to/dir \( -name '*.css' -o -name '*.html' \) -exec gzip --verbose --keep {} \;

변경 nameiname당신이 대문자와 소문자를 구별하지 않고로 확장 일치 할 경우 (즉, 포함 .CSS및 / 또는 .HTML확장). /path/to/dir현재 디렉토리에서 재귀 검색을 시작하려는 경우를 생략 할 수 있습니다 .


2
--keep스위치 에 대해 궁금한 사람들에게는 예, 원본 파일이 유지됩니다. 일단 gzipped되면 삭제되도록하려면 생략하십시오.
벤 존슨

4

파일 목록을 얻으려면

find -type f | grep -P '\.js|\.html|\.css'

그리고 모든 파일을 압축하려면 :

find -type f | grep -P '\.js|\.html|\.css' | tar cvzf archive.gz -T -

하지이겠습니까 의 목록을 출력으로 파일이 아니라 파일 자체보다 더? tarfind
Jos

각 css, html 또는 js 파일에 대한 아카이브 파일을 갖고 싶다는 것을 분명히하기 위해 질문을 편집했습니다.
Sadik

2
-T옵션 이있는 @Jos no tar는 입력을 파일 이름으로 처리합니다.
혼돈

@chaos 아, 감사합니다. 나는 오늘 무언가를 배웠다.
Jos

2

나는 steeldriver 's answer을 사용 했지만 --best--force옵션 으로 완성하고 싶습니다 .

cd아무 폴더 에나이 코드를 입력하십시오. 일치하는 모든 파일이 압축됩니다.

find . \( -name '*.css' -o -name '*.js' \) -exec gzip --verbose --keep --best --force {} \;
  • --best최상의 압축비를 위해 사용하십시오 .
  • --force이미 zip 파일이 있는지 묻지 않고 덮어 쓰기에 사용 합니다.

1

globstar를 사용할 수 있습니다.

으로 globstar쉘 옵션이 활성화, 당신이 필요로하는 모든입니다 gzip -vk **/*.{css,html}.

Bash 셸에는 globstar을 사용 하여 재귀 글로브 를 작성할 수 있는 옵션이 있습니다 **. shopt -s globstar가능하게합니다. 그러나 나중에 실행하는 다른 명령의 경우이를 수행하지 않으려 gzip 는 경우 대신 서브 쉘 에서 명령 과 명령을 실행할 수 있습니다 .

이 명령은 gzip모든이야 .css.html모든 하위 디렉토리의 현재 디렉토리에있는 파일을, 모든 그들의 등 하위 디렉토리 (원본 파일을 유지 -k)하고 (무엇을하고 있는지 알려주 -v) :

(shopt -s globstar; gzip -vk **/*.{css,html})

대소 문자를 구분하지 않고 파일 이름을 일치 시키려면 대문자 또는 일부 문자가 포함 된 확장명이 포함되도록 nocaseglob쉘 옵션을 활성화 할 수도 있습니다.

(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})

;두 명령을 분리하면 외부 명령 ( )이 하위 쉘에서 실행됩니다. 서브 쉘에서 쉘 옵션을 설정해도 호출 쉘에서 쉘 옵션이 설정되지 않습니다. 당신 활성화하고 싶다면 globstar당신은 실행할 수 있습니다 shopt -s globstar; 그런 다음 명령을 실행할 수 있습니다.

gzip -vk **/*.{css,html}

당신은 비활성화 할 수 있습니다 globstarshopt -u globstar. 현재 사용하도록 설정되어 있는지 확인할 수 있습니다 shopt globstar.

작동 원리

gzip명령의 작동 방식의 핵심 은 쉘이 확장을 수행하여 디렉토리 계층에서 일치하는 이름으로 각 파일 목록을 생성 한 다음 각 파일 이름을 인수로 전달하는 것 gzip입니다.

  • 가새 확장**/*.{css,html}로 바뀝니다 **/*.css **/*.html.
  • 다음 글 로빙 (현재 디렉토리에 액세스 파일의 이름으로 확장에게 그 두 가지 패턴 **으로 인해, globstar그 파일 이름이 무엇이든 (구성) *) 지정된 접미사 (뒤에 .css또는 .html이 경우).

이름이 시작. 하거나이 방법으로 명명 된 디렉토리에있는 파일과 일치하지 않습니다 . 아마도 그러한 HTML 및 CSS 파일이 없을 것이므로 포함하고 싶지 않을 것입니다. 그러나 포함하고 싶다면 필요에 따라 명시 적으로 일치시킬 수 있습니다. 예를 들어, 여전히 폴더에서 검색 하지 않고 시작하는 파일 **/*.{css,html}**/{,.}*.{css,html}포함 하도록 변경 합니다 ..

이름이 시작하는 파일과 이름이 시작 .되는 디렉토리에있는 파일 .을 모두 포함하려면보다 깔끔하고 간단한 방법이 dotglob있습니다. 쉘 옵션을 활성화하십시오 .

(shopt -s globstar dotglob; gzip -vk **/*.{css,html})

또는 당신은 대소 문자를 구분하지 일치하려는 경우 로 시작하는 파일 이름의 일치를 .:

(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})

아주 드물기는하지만 **너무 길게 확장 될 수 있습니다.

당신이있는 경우 거대한 이런 식으로 이름이 지정된 파일의 수를, 다음이 너무 긴 것 때문에 쉘이 명령 줄을 구축 할 수 없음을 설명하는 오류 메시지와 함께 실패 할 수 있습니다. (심지어 수천 개의 파일로, 이것은 보통 문제가되지 않습니다.)

gzip 전혀 부름을받지 않기 때문에 절반의 일을 할 수 없습니다.

이 오류가 발생하면 당신이 그것에 대해 걱정하는 경우, 또는, 당신은 사용할 수 있습니다 find-exec, 하나 같이 steeldriver 설명 (과 {} \;) 또는 나는 (함께 아래 설명 {} +).

작업과 find함께 사용 하고 효율성을 높일 수 있습니다.-exec+

gzip명령은 압축 할 여러 파일의 이름을 제공합니다. 그러나이 find명령은 잘 작동하지만 파일 이 많지 않으면 속도가 느리지 않지만 파일 마다gzip 한 번씩 명령을 실행 합니다.

find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;

이것은 작동하며 확실히 사용할 수 있습니다. ( .현재 디렉토리에서 검색합니다. 그 외에도, 스틸 드라이버의 훌륭한 답변으로 명령을 작성하는 방법이 약간 다릅니다 . 원하는 스타일을 사용할 수 있습니다.)

또한 find여러 파일 이름을 전달 gzip하고 필요한 횟수만큼만 실행할 수 있습니다 ( 거의 항상 한 번). 그렇게하려면 대신을 사용하십시오+\; . +인수는 바로 뒤에 와야한다 {}. 추가 파일 이름 (있는 경우)으로 find바꿉니다 +.

find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +

+일치하는 파일이 적은 경우에도 사용하는 것이 좋으며 많은 gzip파일이있는 경우 각 파일에 대해 별도의 호출을 하는 것보다 훨씬 빠릅니다 .

steeldriver가 언급 했듯이 이름이 같 거나 대소 문자가 다른 파일을 일치시키는 -iname대신 사용할 수 있습니다 . 이것은 위에서 설명한 기반 방법 에서 활성화하는 것에 해당합니다 .-name.css.htmlnocaseglobglobstar

마지막으로로 시작하는 일치하는 파일이나 디렉토리가 없을 것입니다 .. 그러나 그렇게하면 find자동으로 포함시킵니다. 당신이 원하는 경우 제외 합니다 (로 어떻게 그들을 globstar때보다 자세히 기반 방법 dotglob꺼짐), 당신은 할 수 있습니다 :

find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +

globstar기반 방법은 위에서 설명한 당신이 시작을 제외한 디렉토리와 파일을있어 특히, 쓰기에 간단 .그 기본이기 때문에.

무엇을 하지 해야 할 일 ...

파일 이름은 경로 구분 기호 /널 문자를 제외한 모든 문자를 포함 할 수 있습니다 . 이상한 파일 이름을 사용하는 많은 기술이 있으며 일반적으로 항상 작동하는 기술보다 더 복잡 합니다. 따라서 특정 상황에서 괜찮다는 것을 알고 (또는 알고 있다고 생각할 때) 피하는 것이 좋습니다. 물론 공백을 포함하여 특수하게 취급 될 수있는 문자가 포함 된 파일 이름이있을 경우이를 사용 해서는 안됩니다.

줄 바꿈 대신 경로 사이에 널 (null) 문자를 배치하도록하는 다른 조치 또는 유사한 조치를 사용find 하는 경우-print0 이를 처리하는 다른 명령으로 출력을 안전하게 파이프하는 것이 가능합니다 . 파일 이름에는 줄 바꿈이 포함될 수 있습니다 (심지어 파일 이름을 의도적으로 지정하는 것을 권장하지는 않습니다). find와 명령 -print조치 - 명시적인 행동으로 찾기 명령을 포함하여, 이후 다음은 -print기본입니다 - 안전하게 다른 명령에 제공 그렇지 않으면 파이프 나 할 수 출력을 생성하지 않는 수행 파일에 대한 작업.

액션 find과 함께 생성 된 출력 은 -print0안전하게 파이프로 연결될 수 있습니다 xargs -0( -0플래그는 xargs널로 분리 된 입력을 예상 함).


0

폴더 / 하위 폴더의 모든 파일을 재귀 적으로 압축하려면 :

gzip -r `find . -type f -name "*.html"` 

압축을 풀려면

gunzip -r `find . -type f -name "*.gz"` 

명령 대체 기반 방법은 자주 중단되며 상당히 나쁩니다. 문제는 공백이나 다른 공백을 포함하는 파일 이름이 분할되어 여러 파일 이름으로 취급된다는 것입니다. (이러한 명령은 ` `구문을 사용하여 작성 되었지만 $( )구문을 사용할 때도 문제가 완전히 적용됩니다 .)
Eliah Kagan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.