Câu trả lời:
Đây là giải pháp đơn giản mà bạn có thể nên sử dụng:
mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif
Không có gì đặc biệt về .keepphần mở rộng, điều này chỉ làm cho nó để tên tệp tạm thời không kết thúc .gif.
Nếu bạn không được đổi tên tệp (và có các tình huống kịch bản trong đó điều này rất quan trọng):
for X in *.gif; do
    if [ "$X" != "filename.gif" ]; then
        rm "$X"
    fi
done
Hoặc bạn có thể viết nó ngắn hơn như thế này:
for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; doneBạn có thể thích sử dụng findthay thế; nó rất mạnh, bạn có thể xem nó dễ đọc hơn và xử lý tốt hơn các tên tập tin kỳ lạ với các nhân vật như *trong đó .
find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -deleteTôi đã sử dụng -nottoán tử để dễ đọc, nhưng nếu tuân thủ POSIX là quan trọng - nếu bạn không sử dụng GNU find hoặc nếu đây là tập lệnh bạn định phân phối lại cho người khác hoặc chạy trên nhiều hệ thống khác nhau - bạn nên sử dụng !toán tử thay thế:
find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -deleteMột điều tiện lợi findlà bạn có thể dễ dàng sửa đổi lệnh không phân biệt chữ hoa chữ thường, để nó tìm và xóa các tệp có phần mở rộng như .GIF:
find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -deleteXin lưu ý rằng tôi đã sử dụng -inamethay -namecho mẫu tìm kiếm *.gifnhưng tôi chưa sử dụng nó cho filename.gif. Có lẽ bạn biết chính xác tệp của bạn được gọi là gì và -inamesẽ khớp với viết hoa thay thế không chỉ trong phần mở rộng , mà bất kỳ nơi nào trong tên tệp.
Tất cả các giải pháp này chỉ xóa các tập tin cư trú ngay lập tức trong thư mục hiện tại . Họ không xóa các tệp không có trong thư mục hiện tại và họ không xóa các tệp nằm trong thư mục con của thư mục hiện tại.
Nếu bạn muốn xóa các tệp ở mọi nơi có trong thư mục hiện tại (nghĩa là bao gồm trong các thư mục con và thư mục con của các thư mục con đó, v.v. - các tệp có trong thư mục hiện tại hoặc bất kỳ hậu duệ nào của nó), hãy sử dụng find mà không maxdepth -1 :
find . -not -name 'filename.gif' -name '*.gif' -deleteHãy cẩn thận với điều này!
Bạn cũng có thể đặt các giá trị khác với -maxdepth. Ví dụ: để xóa các tệp trong thư mục hiện tại và con cháu của nó nhưng không sâu hơn:
find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -deleteChỉ cần chắc chắn rằng bạn không bao giờ đặt -deleteđầu tiên, trước các biểu thức khác! Bạn sẽ thấy tôi luôn luôn đặt -deleteở cuối. Nếu bạn đặt nó ở đầu, nó sẽ được đánh giá đầu tiên và tất cả các tệp trong .(bao gồm các tệp không kết thúc .gifvà các tệp trong thư mục phụ phụ phụ sâu .) sẽ bị xóa!
Để biết thêm thông tin , vui lòng xem trang hướng dẫn cho bashvà shvà cho các lệnh được sử dụng trong các ví dụ: mv, rm, [, và (đặc biệt) find.
find, rất linh hoạt.
                    findxử lý tên tập tin kỳ lạ với *chúng tốt hơn vòng lặp for? Vòng lặp for xử lý các tệp *tốt, vì bạn đã sử dụng dấu ngoặc kép.
                    Nếu bạn đang sử dụng bash(shell mặc định), extglobtùy chọn shell cho phép bạn sử dụng cú pháp khớp mẫu mở rộng. Để kích hoạt nó, hãy sử dụng shoptlệnh dựng sẵn:
shopt -s extglob(Tôi bao gồm dòng đó trong .bashrctập tin của tôi .)
Trong số những thứ khác, nó cấp quyền truy cập cho !()toán tử, phù hợp với bất kỳ mẫu nào không nằm trong parens. Vì mục đích của bạn:
rm !(filename).gifThông tin thêm có sẵn trong man bash"Kết hợp mẫu".
extglobphải được kích hoạt, nhưng không có gì xấu xảy ra nếu nó bị vô hiệu hóa (trong trường hợp đó, điều này chỉ không hoạt động). Và nó dường như được bật theo mặc định, mặc dù tôi không có shopt -s extglobtrong bất kỳ tệp cấu hình nào (hoặc toàn cầu). Nếu có một lời giải thích đơn giản về lý do tại sao nó hoạt động cho tôi ra khỏi hộp, bạn có thể muốn thêm nó vào câu trả lời này; hoặc tôi có thể gửi một câu hỏi mới.
                    Mở Terminal bằng Ctrl+ Alt+ Tvà gõ:
find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;Sự khác biệt giữa -deletevà -exec rm -vf {} \;là với tùy chọn thứ hai, bạn sẽ có thể xem tập tin nào đã bị xóa, vì -vcờ. Đó là điều không thể được thực hiện với -deletetùy chọn. ( -name -deleteSẽ in tên tập tin, nhưng rmvới -vtiết lộ nếu mỗi tập tin được thành công xóa.)
Có GLOBIGNOREbiến. Từ man bash:
GLOBIGNORE
      A colon-separated list of patterns defining the set of filenames
      to be ignored by pathname expansion.  If a filename matched by a
      pathname expansion pattern also matches one of the  patterns  in
      GLOBIGNORE, it is removed from the list of matches.Vì vậy, một cách đơn giản là chỉ đặt GLOBGINOREtên tệp trong câu hỏi:
$ touch {a,b,c,d}.png
$ echo *.png
a.png b.png c.png d.png
$ GLOBIGNORE=c.png
$ echo *.png
a.png b.png d.pngVì vậy, trong trường hợp của bạn:
GLOBIGNORE=filename.gif; rm *.gifTất nhiên, vì GLOBIGNOREcó chứa các mẫu, bạn có thể sử dụng nó bất cứ khi nào bạn muốn loại trừ một mẫu:
$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.pngMột lợi thế (?!) GLOBIGNORELà cài đặt nó tự động loại trừ .và.. không khớp, và nó cho phép dotglob:
The  GLOBIGNORE shell variable may be used to restrict the set of file‐
names matching a pattern.  If GLOBIGNORE is set, each matching filename
that also matches one of the patterns in GLOBIGNORE is removed from the
list of matches.  The filenames ``.''  and ``..''  are  always  ignored
when  GLOBIGNORE is set and not null.  However, setting GLOBIGNORE to a
non-null value has the effect of enabling the dotglob shell option,  so
all other filenames beginning with a ``.''  will match.  To get the old
behavior of ignoring filenames beginning with a ``.'', make ``.*''  one
of  the  patterns  in  GLOBIGNORE.  The dotglob option is disabled when
GLOBIGNORE is unset.Vì vậy, một cách đơn giản để xóa tất cả các tệp và thư mục trong một thư mục:
GLOBIGNORE=.; rm -r *Tên *tệp sẽ khớp với tên bắt đầu bằng ., kể từ khi GLOBIGNOREđược bật dotglob, nhưng nó sẽ không khớp .hoặc ..vì vậy bạn sẽ không ảnh hưởng đến thư mục mẹ theo cách đó.