Evite listar os arquivos que terminam com ~ (arquivos de backup)

20

Meu requisito é listar todos os arquivos em um diretório, exceto os que terminam com a ~(arquivos de backup).

Eu tentei usar o comando:

ls -l | grep -v ~    

Eu recebo esta saída:

asdasad
asdasad~
file_names.txt
normaltest.txt
target_filename
testshell1.sh
testshell1.sh~
testshell2.sh
testshell2.sh~
testtwo.txt
testtwo.txt~
test.txt
test.txt~

Quero obter apenas esses arquivos:

asdasad
file_names.txt
normaltest.txt
target_filename
testshell1.sh
testshell2.sh
testtwo.txt
test.txt
curious_one
fonte
Parece que você está tentando evitar listar arquivos que terminam com a ~. Esses arquivos são arquivos de backup criados em alguns editores de texto.
ctrl-alt-delor 26/09/18
Qual sistema operacional você está usando: é um Gnu / Linux (como Debian, Ubuntu, Redhat, Centos, Fedora, Suse, Mint, Arch, ...)?
ctrl-alt-delor 26/09/18
2
Observe que o arquivo que você deseja ignorar parece ser um arquivo de backup do Emacs. É bastante fácil alterar o comportamento do Emacs para salvar backups em um diretório centralizado e não em todo o lugar; consulte emacs.stackexchange.com/questions/33/…
Kilian Foth
Sinto muito por ser mau, mas não acredito em você; ls -l(letter ell) incluiria permissões, nlinks, proprietário, tamanho e tempo de modificação para cada arquivo listado. O que produziria a saída que você mostra é ls -1(dígito um) e em muitos sistemas -1é necessário para produzir uma saída em coluna única no terminal , mas quando lsé canalizado (como aqui para grep) ou redirecionado, -1não é necessário, já é uma coluna .
Dave_thompson_085 30/09
@ dave_thompson_085 Trunquei todo o texto e apenas os nomes de arquivos aqui .. Porque eu senti que isso é irrelevante. E também este é um sistema de produção (não o meu próprio sistema). Então, eu não quero listar nomes de usuários, detalhes e vazá-los.
Curious_one

Respostas:

49
ls -l | grep -v ~

A razão pela qual isso não funciona é que o til é expandido para o diretório inicial e, portanto, grepnunca vê um til literal. (Veja, por exemplo, o manual do Bash sobre a expansão de Tilde .) Você precisa citá-lo para impedir a expansão, ou seja,

ls -l | grep -v "~"

Obviamente, isso ainda removerá qualquer linha de saída com um til em qualquer lugar, mesmo no meio de um nome de arquivo ou em outro local da lssaída (embora provavelmente não seja provável que apareça em nomes de usuário, datas ou outras). Se você realmente deseja apenas ignorar arquivos que terminam com um til, você pode usar

ls -l | grep -v "~$"
ilkkachu
fonte
48

A implementação GNU de ls(encontrada na maioria dos sistemas Linux) tem uma opção para isso: -BIgnorar backups:

ls --ignore-backups
hschou
fonte
24

Se você estiver usando o bash, verifique se extglobestá ativado:

shopt -s extglob

Então você pode usar:

ls -d -- !(*~)
  • -d para não mostrar o conteúdo dos diretórios
  • !(*~) todos os arquivos, exceto os que terminam com ~

No zsh, você pode fazer o mesmo com a kshglobopção ou usando seus próprios globos estendidos:

setopt extended_glob
ls -d -- ^*~

Como o sufixo a ser excluído tem apenas um caractere, você também pode corresponder aos nomes de arquivos em que o último caractere não é o til (isso também deve funcionar sem extglob):

ls -d -- *[^~]

Mas a ideia geral é usar ls --ignore-backups.

Ravexina
fonte
12

Isso deve ajudar:

ls -l | grep -v '~'  

Razão: O ~ char é substituído pelo seu diretório inicial antes que o comando seja executado. Experimentar

echo ~

e

echo '~'
Nico Mittenzwey
fonte
6

Como mencionado em outras respostas, é provável que você tenha problemas porque não citou ou escapou do til.

Para um caso de uso específico, usei a expansão de nome de arquivo do shell para fazer algo semelhante. Eu o uso desde 2003, o que significa que ele trabalhou em uma variedade muito ampla de implementações de shell em diferentes tipos de sistemas. (aqui eu também uso -Cporque quero uma boa exibição em colunas classificadas)

ls -C *[!~]

(uma limitação ao usar a expansão de nome de arquivo shell é que um diretório com um número muito grande de arquivos (sem backup) fará com que a expansão exceda o tamanho da lista de argumentos disponível, embora na maioria dos sistemas modernos esse limite seja bastante alto, geralmente 250 KB ou mais, às vezes muito mais)

Greg A. Woods
fonte
1

ls | grep -v '~$'é a solução rápida. Ele usa ls para listar todos os arquivos (não ocultos) e, em seguida, usa grep com -v(correspondência invertida, ou seja, exclusão) para excluir todas as linhas com o til ( ~) no final ( $).

No entanto, se você tiver QUALQUER arquivo nomeado como algo1, algo2, é um enorme indicador fedorento de que você tem um fluxo de trabalho ruim, que deve ser corrigido na fonte, não com hacks desajeitados, como modificar o funcionamento do ls.

Se você estiver nomeando arquivos com números de versão, como test1 e test2 ou testone e testtwo, o que realmente deseja é um sistema de controle de versão git.

Isso é especialmente verdade no seu caso, onde você tem várias versões de vários arquivos, e o controle de versão parece precisar ser coordenado entre todos os arquivos.

Os sistemas de controle de versão permitem que você sobreponha essencialmente uma janela de tempo no sistema de arquivos, para que você veja apenas um testarquivo, mas sob o capô (através do programa de controle de versão) todas as versões estão disponíveis para pesquisar, recuperar, reverter para, comparar com etc. .

Depois de configurá-lo, você não precisa mais dos arquivos de backup do seu editor, porque o controle de versão possui o histórico dos arquivos desde que você começou a usá-lo, mesmo que você tenha feito mil alterações desde então. Você pode até "ramificar" a linha do tempo do histórico, experimentando uma nova idéia e voltar no tempo e, em seguida, avançar para tentar uma idéia diferente, se necessário.

por favor me apague
fonte
1

Embora muitas respostas estejam corretas (eu gosto especialmente das respostas @Foon), eu observaria que obter a lista de nomes ls -lé um pouco ruim por vários motivos.

A ferramenta adequada para encontrar arquivos é, sem surpresa find,.

Uma de suas conclusões é que é capaz de lidar com a "lógica de seleção" sozinha, por exemplo:

$ find . -maxdepth 1 \( -type f -a \! -name '*~' \) -print

que literalmente diz find:

  1. Procure arquivos no diretório atual: .
  2. Procure-os apenas no nível desse diretório - ou seja, não recorra: -maxdepth 1
  3. Lá, procure entidades que

    • do tipo arquivo: -type f
    • e: -a
    • cujos nomes não terminam em ~: ! -name *~ (onde !nega a seguinte diretiva que corresponde aos nomes dos arquivos -name *~).

    (Para fazer com que toda a correspondência entre tipo e nome apareça como uma unidade lógica, ela deve estar entre parênteses com (e )).

  4. Imprimir o nome de cada arquivo encontrado: -print.

Você precisa proteger alguns caracteres especiais para o shell de serem interpretados pelo shell, e é por isso que os parênteses e o estrondo !são escapados por barra invertida e o padrão de nome *~é cercado por aspas simples.

O findcomando possui uma minilíngua muito poderosa através do uso de suas opções. Por exemplo, pode ser dito para processar recursivamente toda uma árvore (ou árvores) do sistema de arquivos, mas omitir certos diretórios durante a verificação. É possível corresponder a vários atributos dos arquivos - como tempo de criação ou modificação ou tamanho de qualquer que seja.

kostix
fonte