[0-9A-Z]{1,2}_\d{4}_\w+?\.dat
예를 들어 , 와 A1_2001_pm23aD.dat
같은 이름이 일치하는 파일을 유지하고 K_1998_12.dat
나머지는 삭제하고 싶습니다 .
그러나 ls
및 rm
명령은 이러한 정규식을 지원하지 않습니다. 어떻게 해야 하나요?
답변1
확장된 글로브를 사용하십시오:
shopt -s extglob
printf '%s\n' !([[:digit:][:upper:]]?([[:digit:][:upper:]])_[[:digit:]][[:digit:]][[:digit:]][[:digit:]]_+([[:alnum:]]).dat)
이는 !
()와 일치하지 않는 모든 파일/디렉토리 이름을 인쇄하고 [[:digit:][:upper:]]
그 뒤에 0 또는 1, s 사이에 4 [[:digit:][:upper:]]
, 확장자 앞에 하나 이상이 옵니다. 재귀적으로 검색하려면 다음을 수행하세요.[[:digit:]]
_
[[:alnum:]]
.dat
shopt -s globstar
shopt -s extglob
printf '%s\n' **/!([[:digit:][:upper:]]?([[:digit:][:upper:]])_[[:digit:]][[:digit:]][[:digit:]][[:digit:]]_+([[:alnum:]]).dat)
또는 다음을 사용하십시오 gnu find
(정규식을 사용할 수 있음).
find . -regextype egrep ! -regex '.*/[[:digit:][:upper:]]{1,2}_[[:digit:]]{4}_[[:alnum:]]+\.dat$'
답변2
이를 수행하는 방법에는 여러 가지가 있습니다. 정규식을 이해하는 스크립트 언어를 사용할 수 있습니다. 예를 들어 Perl에서는 다음과 같습니다.
perl -le 'unlink(grep(!/[0-9A-Z]{1,2}_\d{4}_\w+?.dat/,@ARGV))' *
그러면 모든 파일이 검색됩니다(하위 디렉터리가 아닙니다.) 현재 디렉터리에서 정규식과 일치하지 않는 내용을 모아서 삭제합니다.
bash를 사용하여 비슷한 작업을 수행할 수도 있습니다. 정규식을 POSIX ERE로 변환하면 됩니다.
for f in *; do
[[ "$f" =~ [0-9A-Z]{1,2}_[0-9]{4}_[a-zA-Z0-9]+.dat ]] || rm "$f";
done
정규식에서는 \w+?.dat
가능한 가장 작은 영숫자 문자열과 일치시키려는 시도가 이루어집니다.모든 문자그리고 dat
. .+?
\.dat
foobarfoobarfoobarA1_2001_pm23aD.datfoobarfooabr
그렇다면 대신 다음 중 하나를 사용하십시오.
perl -le 'unlink(grep(!/^[0-9A-Z]{1,2}_\d{4}_\w+\.dat$/,@ARGV))' *
또는
for f in *; do
[[ "$f" =~ ^[0-9A-Z]{1,2}_[0-9]{4}_[a-zA-Z0-9]+.dat$ ]] || rm "$f";
done
마지막으로 디렉터리를 삭제하려면 다음을 수행할 수 있습니다.
for f in *; do
[[ "$f" =~ ^[0-9A-Z]{1,2}_[0-9]{4}_[a-zA-Z0-9]+.dat$ ]] || rm -rf "$f";
done
답변3
당신은 이것을 할 수 있습니다 find
:
find . -regextype posix-extended \
-type f ! -regex '.*/[0-9A-Z]{1,2}_[[:digit:]]{4}_[[:alnum:]_]+?\.dat' -delete
- 물론 한 줄에 모두 넣을 수 있습니다(
\
첫 번째 줄 끝의 항목을 제거하세요). -regextype posix-egrep
정확하게 잘 작동하는 것 같습니다-regextype posix-extended
.find
귀하의 버전이 이를 지원하지 않는 경우 또는 를-delete
사용하십시오 .-exec rm -- {} +
-exec rm -- {} ';'
- 최상위 디렉터리만 검색하려면 를 사용하세요
-maxdepth 1
.