Remove todos os arquivos / diretórios, exceto para um arquivo

201

Eu tenho um diretório contendo um grande número de arquivos. Eu quero excluir todos os arquivos, exceto para file.txt. Como faço isso?

Existem muitos arquivos para remover os indesejados individualmente e seus nomes são muito diversos para serem usados * para removê-los, exceto este arquivo.

Alguém sugeriu usar

rm !(file.txt)

Mas isso não funciona. Ele retorna:

Badly placed ()'s 

Meu sistema operacional é o Scientific Linux 6.

Alguma ideia?

    
por Derek 05.09.2014 / 03:59

7 respostas

243

POSIXly:

find . ! -name 'file.txt' -type f -exec rm -f {} +

removerá todos os arquivos regulares (recursivamente, incluindo os ocultos), exceto file.txt . Para remover diretórios, altere a opção -type f para -type d e adicione -r para rm .

Em bash , para usar rm -- !(file.txt) , você deve ativar extglob :

$ shopt -s extglob 
$ rm -- !(file.txt)

(ou chamando bash -O extglob )

Observe que extglob só funciona em bash e na família de shell Korn. E usar rm -- !(file.txt) pode causar um erro Argument list too long .

Em zsh , você pode usar ^ para negar padrão com extendedglob ativado:

$ setopt extendedglob
$ rm -- ^file.txt

ou usando a mesma sintaxe com ksh e bash com as opções ksh_glob e no_bare_glob_qual ativadas.

    
por 05.09.2014 / 04:02
87

Outra direção diferente (se não houver espaços nos nomes dos arquivos)

ls | grep -v file.txt | xargs rm

ou (funciona mesmo se houver espaços nos nomes dos arquivos)

ls | grep -v file.txt | parallel rm

de man grep :

 -v, --invert-match
          Invert the sense of matching, to select non-matching lines.  (-v is specified by POSIX)
    
por 06.09.2014 / 11:49
27

Mantenha uma cópia, exclua tudo, restaure a cópia:

{   rm -rf *
    tar -x
} <<TAR
$(tar -c $one_file)
TAR

Em uma linha:

{ rm -rf *; tar -x; } <<< $(tar -c $one_file)

Mas isso requer um shell que suporte aqui strings.

    
por 05.09.2014 / 04:33
15

No meu SO Scientific Linux 6 isso funciona:

shopt -s extglob
rm !(file.txt)

Eu também tenho o Debian 32bit instalado em uma máquina virtual. O acima não funciona, mas o seguinte faz:

find . -type f ! -name 'file.txt' -delete
    
por 05.09.2014 / 04:27
15

você está pensando demais nisso.

cd ..
mv fulldir/file.txt /tmp/
rm -rf fulldir
mkdir fulldir
mv /tmp/file.txt fulldir/

Feito.

EDITAR Na verdade, é mais fácil:

cd ..
ln fulldir/file.txt ./
rm -rf fulldir
mkdir -p fulldir
mv file.txt fulldir/
    
por 05.09.2014 / 14:32
7

Use rm !("file.txt") em vez de rm !(file.txt)

    
por 06.09.2014 / 13:04
6

Só para dar uma resposta diferente, você pode usar o comportamento padrão de rm para não excluir pastas:

mkdir tmp && mv file.txt tmp  # create tmp dir and move files there
rm                            # delete all other files
mv tmp/* . && rm -rf tmp      # move all files back and delete tmp dir
    
por 20.09.2017 / 17:22