Respostas:
Aqui está a solução simples que você provavelmente deve usar:
mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif
Não há nada de especial na .keepextensão, isso apenas faz com que o nome do arquivo temporariamente não termine .gif.
Se você não deve renomear o arquivo (e há situações de script em que isso é importante):
for X in *.gif; do
if [ "$X" != "filename.gif" ]; then
rm "$X"
fi
done
Ou você pode escrever mais curto assim:
for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done
Você pode preferir usar find; é muito poderoso, você pode considerá-lo mais legível e lida melhor com nomes de arquivos estranhos com personagens como *eles .
find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete
Usei o -notoperador para facilitar a leitura, mas se a conformidade com POSIX for importante - se você não estiver usando o GNU find, ou se for para um script que pretende redistribuir para outras pessoas ou executar em uma variedade de sistemas - você deve use o !operador:
find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete
Uma coisa útil findé que você pode modificar facilmente o comando para diferenciar maiúsculas de minúsculas, para que ele encontre e exclua arquivos com extensões como .GIF:
find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete
Observe que eu usei -inameno lugar do -namepadrão de pesquisa, *.gifmas não o usei filename.gif. Presumivelmente, você sabe exatamente como o seu arquivo é chamado e -inamecorresponderá a maiúsculas e minúsculas alternativas não apenas na extensão , mas em qualquer lugar do nome do arquivo.
Todas essas soluções excluem apenas os arquivos que residem imediatamente no diretório atual . Eles não excluem arquivos não contidos no diretório atual e não excluem arquivos que residem em subdiretórios do diretório atual.
Se você deseja excluir os arquivos em todos os lugares contidos no diretório atual (ou seja, incluindo subdiretórios e subdiretórios desses subdiretórios, e assim por diante - arquivos contidos no diretório atual ou em qualquer um de seus descendentes), use find sem maxdepth -1 :
find . -not -name 'filename.gif' -name '*.gif' -delete
Tenha cuidado com isso!
Você também pode definir outros valores com -maxdepth. Por exemplo, para excluir arquivos no diretório atual e seus filhos e netos, mas não mais:
find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete
Apenas certifique-se de nunca colocar -deleteprimeiro, antes das outras expressões! Você verá que eu sempre coloco -deleteno final. Se você colocá-lo no início, ele será avaliado primeiro e todos os arquivos em .(incluindo arquivos que não terminam em .gife arquivos em sub-sub-sub-sub ... subdiretórios profundos ... .) serão excluídos!
Para mais informações , consulte as páginas do manual para bashe she para os comandos utilizados nestes exemplos: mv, rm, [, e (especialmente) find.
find, o que é altamente versátil.
findlidar com nomes de arquivos estranhos com *eles melhor do que o loop for? O loop for lida com arquivos com *precisão, porque você usou aspas duplas.
Se você estiver usando bash(o shell padrão), a extglobopção shell permitirá que você use uma sintaxe de correspondência de padrão estendida. Para habilitá-lo, use o shoptcomando embutido:
shopt -s extglob
(Incluo essa linha no meu .bashrcarquivo.)
Entre outras coisas, concede acesso ao !()operador, que corresponde a qualquer padrão que não esteja dentro do parens. Para seu propósito:
rm !(filename).gif
Mais informações estão disponíveis em man bash"Correspondência de padrões".
extglobdeve ser ativada, mas nada de ruim acontece se estiver desativado (nesse caso, isso simplesmente não funciona). E parece estar ativado por padrão, mesmo que eu não possua shopt -s extglobnenhum dos meus arquivos de configuração (ou os globais). Se houver uma explicação simples sobre por que ela funciona para mim imediatamente, você pode adicioná-la a esta resposta; ou posso postar uma nova pergunta.
Abra um terminal com Ctrl+ Alt+ Te digite:
find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;
A diferença entre -deletee -exec rm -vf {} \;é que, com a segunda opção, você poderá ver quais arquivos foram removidos devido ao -vsinalizador. Isso é algo que não pode ser feito com a -deleteopção. ( -name -deleteImprimirá os nomes de arquivos, mas rmcom -vrevela se cada arquivo foi com êxito excluído.)
Existe a GLOBIGNOREvariável. De 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.
Portanto, uma maneira simples é simplesmente definir GLOBGINOREo nome do arquivo em questão:
$ 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.png
Então, no seu caso:
GLOBIGNORE=filename.gif; rm *.gif
Obviamente, como GLOBIGNOREcontém padrões, você pode usá-lo sempre que quiser excluir um padrão:
$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png
Uma vantagem (?!) Disso GLOBIGNOREé que a configuração exclui automaticamente .e.. não corresponde, e permite 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.
Portanto, uma maneira simples de excluir todos os arquivos e pastas em um diretório:
GLOBIGNORE=.; rm -r *
Os *nomes de arquivos correspondentes serão iniciados com ., desde GLOBIGNOREativado dotglob, mas não serão correspondentes .ou .., portanto, você não afetará o diretório pai dessa maneira.