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 .keep
extensã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 -not
operador 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 -iname
no lugar do -name
padrão de pesquisa, *.gif
mas não o usei filename.gif
. Presumivelmente, você sabe exatamente como o seu arquivo é chamado e -iname
corresponderá 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 -delete
primeiro, antes das outras expressões! Você verá que eu sempre coloco -delete
no final. Se você colocá-lo no início, ele será avaliado primeiro e todos os arquivos em .
(incluindo arquivos que não terminam em .gif
e arquivos em sub-sub-sub-sub ... subdiretórios profundos ... .
) serão excluídos!
Para mais informações , consulte as páginas do manual para bash
e sh
e para os comandos utilizados nestes exemplos: mv
, rm
, [
, e (especialmente) find
.
find
, o que é altamente versátil.
find
lidar 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 extglob
opção shell permitirá que você use uma sintaxe de correspondência de padrão estendida. Para habilitá-lo, use o shopt
comando embutido:
shopt -s extglob
(Incluo essa linha no meu .bashrc
arquivo.)
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".
extglob
deve 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 extglob
nenhum 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 -delete
e -exec rm -vf {} \;
é que, com a segunda opção, você poderá ver quais arquivos foram removidos devido ao -v
sinalizador. Isso é algo que não pode ser feito com a -delete
opção. ( -name -delete
Imprimirá os nomes de arquivos, mas rm
com -v
revela se cada arquivo foi com êxito excluído.)
Existe a GLOBIGNORE
variá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 GLOBGINORE
o 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 GLOBIGNORE
conté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 GLOBIGNORE
ativado dotglob
, mas não serão correspondentes .
ou ..
, portanto, você não afetará o diretório pai dessa maneira.