저는 Linux를 처음 사용하는데 MIME 유형을 기반으로 파일을 삭제하는 데 문제가 있습니다. 현재 내 Linux 시스템에는 파일 세트가 있으며 아래에는 일부 유형이 선택되어 있습니다.
0FiTahKc: M3U playlist, ASCII text, with very long lines, with CRLF line terminators
0FJsEpTc: ASCII text, with CRLF line terminators
0fKPkmwe: ASCII text, with CRLF line terminators
0FLR6MWB: ASCII text
0FMa2xL2: C source, ASCII text, with CRLF line terminators
0fN8DDbf: exported SGML document, ASCII text, with very long lines, with no line terminators
0fSM3YyG: ASCII text, with CRLF line terminators
0fTXKtZD: UTF-8 Unicode text, with CRLF line terminators
0FUcusxr: ASCII text, with CRLF line terminators
디렉토리에 있는 다양한 유형의 파일을 살펴보았는데 결과는 다음과 같습니다.
$ find -type f -exec file {} \; | sed 's/^.*: //' | sort -u
ASCII text
ASCII text, with CRLF line terminators
ASCII text, with no line terminators
ASCII text, with very long lines, with CRLF line terminators
ASCII text, with very long lines, with no line terminators
C source, ASCII text, with CRLF line terminators
exported SGML document, ASCII text, with very long lines, with no line terminators
M3U playlist, ASCII text, with very long lines, with CRLF line terminators
M3U playlist, UTF-8 Unicode text, with CRLF line terminators
UTF-8 Unicode text, with CRLF line terminators
"C Source", "M3U Playlist", "SGML" 등에 대해 grep을 사용하거나 Find를 사용하여 디렉토리에서 해당 파일을 삭제하고 싶습니다(처음 5줄의 ASCII 유형 제외). 이러한 파일 형식의 다양한 유형을 파이프하고 삭제할 수 있는 실행할 수 있는 명령이나 스크립트를 찾고 있습니다.
답변1
몇 가지 도구를 한 줄에 함께 넣으십시오.
- 질문에 표시된 대로 각 파일의 MIME 유형을 사용
find
하고 나열하십시오.files
awk
유형을 기준으로 목록을 필터링 하는 데 사용됩니다 .xargs
필터링된 목록과 각 파일을 가져오는 데 사용됩니다rm
.
echo
아무것도 하지 않도록 먼저 사용하는 것이 좋습니다 . rm
그러면 명령이 건조 실행되어 어떤 파일이 삭제될지 확인할 수 있습니다!
예: "C 소스"를 삭제합니다.
find . -type f -exec file {} + | awk -F: '$(NF) ~ "C source" {print $1}' | xargs echo rm
그런 다음 동일한 줄 삭제를 실행하여 echo
실제로 파일을 삭제합니다.
awk를 사용한 필터링을 설명하기 위해 이 절은 awk에게 $(NF) ~ "C source"
두 번째 열( a 이후의 모든 항목 ) :
에 포함된 모든 행 과 일치하도록 지시합니다 C source
. 이 조건은 원하는 대로 확장될 수 있습니다. 따라서 가장 확실하게 다음을 검색 C Source
하거나 M3U playlist
사용할 수 있습니다.
$(NF) ~ "C source" || $(NF) ~ "M3U playlist"
예:
find . -type f -exec file {} + | awk -F: '$(NF) ~ "C source" || $2 ~ "M3U playlist" {print $1}' | xargs echo rm
답변2
file
출력이 파일 이름 :
과 bash 정규식 일치로 시작하는 모든 파일을 제거하려면 다음을 수행하십시오 ASCII text
.find
find -type f -exec bash -c '
for f; do
file=$(file -- "$f")
if [[ $file =~ ^$f:\ "ASCII text" ]]; then
echo rm -- "$f"
fi
done
' bash {} +
C source
, M3U playlist
또는 에도 동일 exported SGML document
:
find -type f -exec bash -c '
for f; do
file=$(file -- "$f")
if [[ $file =~ ^$f:\ ("C source"|"M3U playlist"|"exported SGML document") ]]; then
echo rm -- "$f"
fi
done
' bash {} +
출력이 예상대로 나타나면 echo
이전 콘텐츠를 삭제하세요.rm
답변3
당신이 Bash에 있기 때문에 나는 다음 경로로 갈 것입니다:
#!/bin/bash
[ "$#" -ge 1 ] || { >&2 echo Supply at least one substring; exit 9; }
find . -type f -exec bash -c '
terms=()
nargs=$1
shift
for ((i=1;i<=nargs;i++)); do
terms+=("-e")
terms+=("$1")
shift
done
for f; do
if file -b -- "$f" | grep -Fq "${terms[@]}"; then
echo rm -- "$f"
fi
done
' find-bash "$#" "$@" {} +
다른 이름으로 저장하고 다음을 사용 script.bash
하여 chmod a+x script.bash
실행 가능하게 만듭니다.
./script.bash 'C source' 'M3U playlist' 'SGML'
아이디어는 제거할 용어로 배열을 채운 다음 file
각 파일에 대한 명령 출력을 grep하는 것입니다.
이 옵션은 명령 -b
출력에서 파일 이름을 억제하므로 파일 이름에 개행 문자가 포함되어 있어도 스크립트가 중단되지 않습니다.file
file
처음에 스크립트는 수행할 작업을 에코합니다. 문제가 없다고 확신되면 라인 echo
에서 제거하십시오. rm
몇 가지 실행 예( A<newline>B
문서 참고):
$ file *
a b: empty
A
B: awk or perl script, ASCII text
Active.png: PNG image data, 640 x 384, 8-bit/color RGB, non-interlaced
blanks.bash: Bourne-Again shell script, ASCII text executable
covidActive.gnuplot: ASCII text
data.dat: ASCII text
script.bash: Bourne-Again shell script, ASCII text executable
table.txt: ASCII text
test.sh: POSIX shell script, ASCII text executable
$ ./script.bash awk shell
rm -- ./script.bash
rm -- ./blanks.bash
rm -- ./test.sh
rm -- ./A
B
$ ls
'a b' Active.png covidActive.gnuplot data.dat table.txt
답변4
질문에 태그가 지정되었으므로세게 때리다, 변형프레디의 대답:
(
types=( "C source" "M3U playlist" "exported SGML document" )
IFS='|'
shopt -s globstar dotglob
for f in ./**; do
if [[ $(file -b -- "$f") =~ ^(${types[*]}) ]]; then
echo rm -- "$f"
fi
done
)
- Subshell( )은 기본 환경의 변경을
( ... )
방지하기 위해 사용됩니다 .IFS
IFS
배열이 파이프로 구분된 해당 멤버로 확장되도록 설정합니다(|
아래 첨자 참고).${types[*]}
*
globstar
glob이 모든 파일, 디렉터리 및 하위 디렉터리와 일치하도록 합니다./**
(즉, 파일 이름 확장자는 현재 작업 디렉터리에 루트가 있는 트리를 반복적으로 내려갑니다).dotglob
./**
숨겨진 파일 도 일치시킬 수 있습니다 .(${types[*]})
정규식[[
복합 명령대체 기호( )
로 분리된 유형으로 구성된 그룹 표현식 으로 확장되고, 문자열 시작 부분에|
고정( )되어 잘못된 긍정의 가능성을 줄입니다. 멤버가 POSIX에 특수 문자를 포함하는 경우 작동하지 않을 수 있습니다^
.types
확장 정규식(오히려).
echo
삭제할 파일 목록이 만족스러우면 삭제하세요.