내 작업 디렉터리에 일련의 마크다운 파일이 있습니다.
$ ls *.md
csv_reader.md egrep.md find.md found_pdfs.md osPathSep_help.md readme.md smtplib_help.md today.md
"today.md"를 제외한 항목을 삭제하고 싶습니다.
#!/usr/local/bin/bash
for i in ./*.md ; do
if [[ $i != "today.md" ]]; then
echo $i
fi
done
그것을 실행하고 얻을
$ bash bash/remove_files.sh
./csv_reader.md
./egrep.md
./find.md
./found_pdfs.md
./osPathSep_help.md
./readme.md
./smtplib_help.md
./today.md
하지만 구조화된 명령은 명령줄에서 편리하지 않습니다. 더 짧은 명령으로 이러한 작업을 수행하려면 어떻게 해야 합니까?
답변1
부정 일치 사용(필수 shopt -s extglob
이지만 이미 설정되어 있을 수 있음):
rm !(today).md
ls
(결과를 확인 하는 대신 먼저 사용해도 됩니다 rm
.)
강력해요 extglob
, 당신도 할 수 있어요
rm !(yesterday|today).md
두 파일을 모두 유지하려는 경우.
답변2
find . -maxdepth 1 -name '*.md' ! -name today.md -type f -print
-type f
현재 디렉터리( )에서 모든 파일만 찾아야 합니다( .
또는 디렉터리 이름을 명시적으로 입력해야 합니다)( -maxdepth 1
방지다음 하위 디렉터리.md
)는 ( )로 끝나며 ( ) 파일을 -name '*.md'
포함하지 않습니다 .!
today.md
'*.md'
셸이 실행되기 전에 현재 디렉터리의 .md 파일 목록으로 확장을 시도하지 않도록 작은따옴표를 포함해야 합니다 find
.
삭제할 파일 목록이 인쇄됩니다. 대신 -print
삭제하세요 -delete
.
답변3
위의 방법이 더 나은 솔루션이지만 코드가 작동하지 않는 이유는 비교 때문입니다.
"./today.md"는 "today.md"와 동일하지 않습니다.
답변4
유닉스는 동일한 간단한 작업을 수행하는 다양한 방법을 제공하는 것으로 유명합니다. 어떤 사람들은 을 사용하는 것을 좋아 sed
하지만 저는 를 선호하므로 grep
명령줄에 입력하면 다음을 사용합니다.
rm -i `ls *.md | grep -v '^today.md$'`
ls *.md
가 있는 모든 이름을 나열하십시오.md
.|
결과를ls
다음 명령으로 파이프하지만 부작용으로 인해ls
파일이 한 줄에 하나씩 여러 줄에 나열됩니다.grep -v '^today.md$'
정확히 일치하지 않는 에코 라인today.md
rm -i
그런 다음 결과를 얻으면(명령이 백틱 안에 있기 때문에) 하나씩 삭제할 것인지 묻습니다. 나는 생성된 파일 목록을 사용할 때 생성기에 문제가 발생할 경우를 대비해 항상 이 작업을 수행합니다. 를rm
사용하여 묻지 않고 파일을 삭제할 수 있지만-i
이는 더 위험하며 삭제된 파일 목록을 제공하지 않습니다.