Meu requisito é listar todos os arquivos em um diretório, exceto os arquivos que terminam com a ~
(arquivos de backup).
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~
Eu quero obter apenas esses arquivos:
asdasad
file_names.txt
normaltest.txt
target_filename
testshell1.sh
testshell2.sh
testtwo.txt
test.txt
A implementação do GNU
ls
(encontrada na maioria dos sistemas Linux) tem uma opção para isso:-B
Ignorar backups:A razão pela qual isso não funciona é que o til é expandido para seu diretório inicial, portanto,
grep
nunca vê um til literal. (Veja, por exemplo , o manual do Bash sobre Til Expansion .) Você precisa citá-lo para evitar a expansão, ou seja,Claro, isso ainda removerá todas as linhas de saída com um til em qualquer lugar, mesmo no meio de um nome de arquivo ou em outro lugar na
ls
saída (embora provavelmente não apareça em nomes de usuário, datas ou algo assim). Se você realmente deseja apenas ignorar arquivos que terminam com um til, você pode usarSe você estiver usando o bash, verifique se
extglob
está ativado:Então você pode usar:
-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
kshglob
opção ou usando seus próprios globs estendidos:Como o sufixo a ser excluído tem apenas um caractere, você também pode corresponder nomes de arquivos onde o último caractere não é o til (isso também deve funcionar sem
extglob
):Mas a ideia geral é usar
ls --ignore-backups
.Isso deve ajudar:
Motivo: O ~ char é substituído pelo seu diretório inicial antes que o comando seja executado. Tentar
e
Como mencionado em outras respostas, o motivo pelo qual você provavelmente está tendo problemas é porque você não citou ou escapou do til.
Para um caso de uso específico, usei a expansão de nome de arquivo shell para fazer algo semelhante. Eu o uso desde cerca de 2003, o que significa que ele trabalhou em uma grande variedade de implementações de shell em diferentes tipos de sistemas. (aqui também uso
-C
porque quero uma boa exibição em colunas classificadas)(uma limitação com o uso da 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)
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 QUAISQUER arquivos nomeados como algo1, algo2, é um ENORME indicador fedorento de que você tem um fluxo de trabalho ruim, que você deve corrigir na fonte, não com hacks desajeitados, como modificar como ls funciona.
Se você está nomeando arquivos com números de versão, como test1 e test2 ou testone e testtwo, então o que você realmente quer é um sistema de controle de versão, como
git
.Isso é especialmente verdadeiro 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ê essencialmente sobreponha uma janela de tempo no sistema de arquivos, para que você veja apenas um
test
arquivo, 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, comparar, etc. .Depois de configurar isso, você não precisa mais dos arquivos de backup do seu editor, pois o controle de versão tem 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 da história, experimentando uma nova ideia e voltando no tempo e depois adiante para tentar uma ideia diferente, se necessário.
Embora muitas respostas estejam corretas (eu gosto do
@Foon
's em particular), noto que obter a lista de nomes comls -l
é um pouco chato por vários motivos.A ferramenta adequada para encontrar arquivos é, sem surpresa,
find
.Um de seus resultados é que ele é capaz de lidar com a "lógica de seleção" por si só, por exemplo:
que literalmente diz
find
:.
-maxdepth 1
Lá, procure entidades, que
-type f
-a
~
:! -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, é colocado entre parênteses
(
e)
).-print
.Você precisa proteger alguns caracteres que são especiais para o shell de serem interpretados pelo shell, e é por isso que os parênteses e o bang,
!
, são escapados de barra invertida, e o padrão de nome,*~
, é cercado por aspas simples.O
find
comando possui uma mini-linguagem muito poderosa através do uso de suas opções. Por exemplo, pode ser instruído a processar recursivamente uma árvore (ou árvores) inteira do sistema de arquivos, mas omitir certos diretórios durante a varredura. É possível combinar vários atributos dos arquivos, como tempo de criação ou modificação ou tamanho de qualquer coisa.