Remove arquivos com comprimento 0 dentro do bash

1

Eu quero criar um script bash dentro do terminal Linux para entrar em um arquivo e excluí-lo se estiver vazio:

#!/bin/bash
echo " Enter name of a directory"
read Dir
for Directory in $( ls $HOME )
do 
  test -d $HOME/$dir
  if [ $# -eq 0 ]
  then 
    for filename in $( ls $HOME/$Dir )
    do 
      test -d $HOME/$dir/$filename
      if [ ! -s "$filename"  ]
      then
        rm $HOME/$dir/$filename
      else 
        echo " not empty"
      fi 
    done 
  else 
    echo " $Dir is not a directory" 
  fi 
done

Este é o código que estou usando, mas não funciona. Ele reconhece o arquivo criado, mas não o exclui, mesmo quando está vazio. Salah mostra que não existe tal arquivo ou diretório

    
por Harjot Singh 01.04.2016 / 17:50

2 respostas

4

Editado 1 (Erik Renouf) para se manter em encontrar conforme especificado em The Open Group Base Specifications Questão 6

Editado 2 (WildCard) + assinar e {}

Tente, substitua mydir na linha de comando abaixo com um nome de diretório que precisa ser trabalhado:

find "${HOME}"/mydir -size 0 -type f -exec rm {} +

Ele está removendo todos os arquivos vazios localizados no diretório "$ {HOME}" / mydir e seus subdiretórios (se houver).

Existe uma versão do script abaixo:

#!/bin/bash --
find "${HOME}"/"${1}" -size 0 -type f -exec rm {} +

T E S T

Listar todos os arquivos vazios em testd :

$ find "${HOME}"/testd -size 0 -type f
/home/jay/testd/empty_file.txt

Use o script para remover arquivos vazios:

$ chmod +x clearner.sh
$ ./clearner.sh testd

Verifique se há arquivos vazios:

$ find "${HOME}"/testd -size 0 -type f
$
    
por 01.04.2016 / 18:18
3

Eu gosto de usar find para isso, já que ele lida bem com nomes de arquivos com caracteres especiais. Você poderia fazer isso com o GNU find semelhante a como o @Jay sugeriu ou mais portavelmente como

find "$HOME/$dir" -type f -size 0c -exec rm {} +

, que procurará em $HOME/mydir e todos os subdiretórios. Tudo o que é um arquivo ( -type f ) e tem um tamanho de 0 bytes (-size 0c) terá seu nome aplicado como um argumento para rm , e deixaremos a linha de comando ter muitos argumentos em vez de invocar rm para cada arquivo ( + em vez de \; a -exec )

Se você não quiser descer em subdiretórios e quiser que ele seja portável, você pode fazer o seguinte, que eu vou colocar em um subshell para não mudar do diretório atual no shell atual:

( cd "$HOME/$dir"; find . ! -name . -prune -type f -size 0c -exec rm {} + )

Isso usará -prune para impedir que find entre nos diretórios adicionais e descartará o diretório . , o que impedirá que ele faça parte da lista de diretórios que é descendente. Esses dois resultam em find apenas relatando resultados do diretório atual.

Agora que estamos no diretório atual, podemos revisitar o script que você estava escrevendo, já que estamos muito mais próximos dessa abordagem novamente.

Você deve ter cuidado com a abordagem que estava tentando em seu roteiro. Qualquer arquivo com um caractere em IFS (como um espaço ou tabulação) faria com que seu loop analisasse nomes parciais de arquivos (por exemplo, se um arquivo fosse chamado with space , você obteria with e space em diferentes iterações). Se você for fazer o loop de arquivos em um diretório, é melhor usar globs como

for f in $HOME/$dir/*; do
    if [ -f "$f" ] && [ ! -s "$f" ]; then
       printf "It's an empty file: %s" "$f"
    fi
done

Esta solução da glob não selecionará nenhum arquivo que comece com . , a menos que você ative o dotglob.

    
por 01.04.2016 / 18:46

Tags