나는 오늘 점심 시간에 디렉토리에서 확장자가 없는 파일을 찾아 해당 파일에 파일 확장자를 추가하는 bash 스크립트를 작성했습니다.
여러 플래그와 디렉터리 선택, 파일 복사 또는 덮어쓰기 여부 등을 추가했기 때문에 스크립트는 상대적으로 길지만, 수행하는 작업의 주요 요지는 다음과 같이 간단히 복제할 수 있습니다.
#recursively find files in current directory that have no extension
for i in $(find . -type f ! -name "*.*"); do
#guess that extension using file
extfile=$(file --extension --brief $i)
#select the first extension in the event file spits something weird (e.g. jpeg/jpe/jfif)
extawk=$(echo $extfile | awk -F/ '{print $1}')
#copy the file to a file appended with the extension guessed from the former commands
cp -av $i $i.$extawk
done
내 실제 스크립트에서는 약간 깔끔합니다. 명령을 여기에서 분할하여 왜 이런 식으로 수행했는지 설명할 수 있기를 원했습니다.
내 질문: 내가 선택한 방식으로 find
결합하는 것이 file
가장 쉬운 방법은 아닐 수 있습니다.최고여러 디렉터리에 있는 다양한 파일 형식에 대한 확장자를 재귀적으로 추측하고 추가하는 방법은 무엇입니까?
답변1
for x in $(find …)
실패한공백(일반적) 또는 와일드카드(덜 일반적)를 포함하는 파일 이름. find
.use 를 구문 분석하지 마세요 -exec
.
원하는 작업을 수행하는 zmv 명령을 작성해 보겠습니다. 먼저 검색 패턴을 구축해 보겠습니다.
autoload zmv
zmv -C -o -a -n -Q '(*/)#^*.*(.)' …
-C
파일을 이동하는 대신 복사합니다.-o -a
-a
에 전달되었습니다cp
.-n
아무 조치도 취하지 않고 수행할 작업만 인쇄하는 것을 의미합니다. 만족스러우면 삭제하세요.-v
작업을 수행하고 싶지만 수행 중인 작업도 인쇄하려면 로 바꾸세요.-Q
만들다글로벌 예선패턴에서.(*/)#
0개 이상의 디렉터리와 일치합니다. 그것은 사용한다#
글로벌 운영자(extended_glob
zmv에서는 항상 활성화되어 있습니다).^*.*
이름에 a가 없는 파일을^
일치시키려면 glob 연산자를 사용하십시오 ..
(.)
일반 파일에 대한 일치를 제한하는 glob 한정자입니다.…
대체 텍스트로 대체됩니다. 이는$f
원래 이름을 참조하는 데 사용할 수 있습니다 .
zmv
모든 대체 이름은 대체가 수행되기 전에 평가되며 대체 이름이 이미 존재하거나 충돌하는 경우 오류를 표시합니다. 대체 이름이 원래 이름과 동일한 파일은 건너뜁니다.
이제 대체 텍스트를 작성해 보겠습니다. 우리는 많이 사용할 것이다매개변수 확장특징.
file
연장을 요청하세요 :$(file --extension --brief -- $f)
- 앞에 하나 추가
.
, 교체 준비: ($(echo -n .; file --extension --brief -- $f)
매개변수 확장을 통해 수행할 수도 있습니다:${:-.$(…)}
.) - 제안된 확장자가 여러 개인 경우(슬래시로 구분) 첫 번째 확장자만 유지됩니다.
${$(echo -n .; file --extension --brief -- $f)%%/*}
- 제안된 확장자가 비어 있거나 인 경우
???
삭제합니다(.
또는.???
빈 문자열로 대체).${${$(echo -n .; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}
- 추가된 확장자를
$f
(원래 이름)에 추가합니다. 추가한 내용이 비어 있으면 파일은 변경되지 않은 상태로 유지됩니다.
결과 명령:
zmv -C -o -a -n -Q '(*/)#^*.*(.)' '$f${${$(echo -n .; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}'
이것은 약간 난해하며 교체를 생성하는 코드를 함수에 넣고 zmv … '$(add_extension $f)'
.
답변2
내 생각에 가장 효율적인 방법은 파일의 MIME 유형을 해당 파일이 있는 데이터베이스와 비교하는 것입니다 /usr/share/mime/globs
.
- 구체리눅스에서는파일 확장자. 주어진 예에서 출력은 다음에서 비롯됩니다.전역 파일
application/x-mswinurl:*.url
text/x-mrml:*.mrl
text/x-erlang:*.erl
audio/x-pn-audibleaudio:*.aa
application/x-bzip-compressed-tar:*.tbz2
application/x-netshow-channel:*.nsc
application/x-hdf:*.h4
application/pgp-keys:*.key
text/x-idl:*.idl
text/x-chdr:*.h
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.visio:*.vsd
application/x-hdf:*.h5
video/vnd.mpegurl:*.m4u
- 유형 예제를 설명한 후 --> Linux가 모든 파일을 다음과 같이
text/x-erlang
인식하도록 지시합니다 .*.
얼랜드확장자.erl
[glob]을 사용하면 이것이 바로 -->*.erl
/etc/magic
파일에 포함될 확장자를 추가할 수 있습니다.
따라서 다음 명령을 실행하십시오.
mimetype -bM file
b
논쟁은 단지 당신에게 말해줍니다type-app/extension
(짧게)M
인수는 다음을 의미합니다.마법Linux는 바이트코드, 16진수, 바이너리 형식의 파일을 검사하여 파일이 실제로 주장하는 파일이 맞는지 확인합니다.모방반환하지 않음은
/jpg/png/webp
한 가지 유형만 반환하며 다음보다 작습니다.file --mime-type file
반품:
image/webp
마지막 생각들
mimetype
다음에 가장 적합합니다.바이너리 파일PDF, 이미지, 비디오 등. 이는 바이너리 파일을 확인할 수 있기 때문에 text plain
더 복잡한 것을 식별해야 하기 때문에 텍스트 편집기가 다른 프로그래밍 언어를 식별할 수 있기 때문에 각 프로그래밍 언어에 대한 사용자 및 서버 언어의 도움이 필요합니다. .
재귀의 경우에는나무매우 좋은:
tree -FIi '*.*' | grep -v /$
- 매개변수는 디렉토리에 [슬래시]를 추가하는
F
것입니다 . 예를 들어 →/
folder
folder/
- 인수
I
는 선택 모드*.*
[확장자를 가진 모든 파일을 선택한다는 의미]와 반대이므로 그 반대는 확장자가 아닙니다. - 인수는
i
트리 출력에서 공백을 제거하는 것입니다. grep -v
reverse를 선택하는 것이므로 -F/
매개변수를 추가합니다.나무명령이 시작 부분에 있으므로 디렉터리를 삭제하고 확장자가/$
.
자세한 내용은 여기서 확인하세요무언극 유형