Para arquivos no diretório, apenas echo filename (sem caminho)

98

Como faço para repetir apenas o nome do arquivo de um arquivo se iterar um diretório com um loop for?

for filename in /home/user/*
do
  echo $filename
done;

irá puxar o caminho completo com o nome do arquivo. Eu só quero o nome do arquivo.

Mechaflash
fonte

Respostas:

166

Se você quer uma bashsolução nativa

for file in /home/user/*; do
  echo "${file##*/}"
done

O acima usa a expansão de parâmetro que é nativa do shell e não requer uma chamada para um binário externo, comobasename

No entanto, posso sugerir apenas usar find

find /home/user -type f -printf "%f\n"
SiegeX
fonte
9
Boa resposta. Para aqueles interessados ​​em aprender mais sobre a expansão de parâmetro: wiki.bash-hackers.org/syntax/pe#substring_removal
DougW
1
-printf: primário ou operador desconhecido => unix.stackexchange.com/a/272493/72893
Nobita
2
Considere mudar ${file##*/}para "${file##*/}"para suportar nomes de arquivos com espaços, por exemplo, "Meu nome de arquivo com espaços.txt".
WinEunuuchs2Unix
echo "$ {file ## * /}" retorna uma string vazia
Alessandro C
47

Basta usar basename:

echo `basename "$filename"`

As aspas são necessárias caso $ filename contenha, por exemplo, espaços.

Sean Bright
fonte
3
melhor usar a expansão do parâmetro, não requer chamadas para binários externos.
SiegeX
5
A propósito, `` está obsoleto. Melhor usar $()como Oli fez
SiegeX
1
Desculpe por comentar sobre esta resposta antiga, mas o nome de base não funcionará corretamente para arquivos com espaço. Exemplo: A produção PWD: /test 1, basename $(pwd)saída: test. Testado em OS X e Ubuntu Server (14.04). A solução bash nativa, conforme recomendado por @SiegeX, é o que funcionou para mim.
Marko Grešak
@ MarkoGrešak Use em seu basename "$(pwd)"lugar.
YoungFrog
@YoungFrog obrigado pela contribuição, mas isso foi há 9 meses. Além disso, seria melhor usar a variável em $PWDvez de executar o comando.
Marko Grešak
15

Use basename:

echo $(basename /foo/bar/stuff)
Oliver Charlesworth
fonte
Por que você usa echo? basenamejá imprime os resultados. echopode até destruir o resultado se você não citar o subshell. Exemplo: echo $(basename path/with\ \ spaces)imprime incorretamente with spaces(apenas um espaço).
Socowi
7

Outra abordagem é usar ls ao ler a lista de arquivos em um diretório para fornecer o que você deseja, ou seja, "apenas o (s) nome (s) do arquivo". Ao contrário de ler o caminho completo do arquivo e, em seguida, extrair o componente "nome do arquivo" no corpo do loop for.

Exemplo abaixo que segue seu original:

for filename in $(ls /home/user/)
do
  echo $filename
done;

Se você estiver executando o script no mesmo diretório dos arquivos, ele simplesmente se tornará:

for filename in $(ls)
do
  echo $filename
done;
Ryan
fonte
1
lsinclui qualquer arquivo de ponto onde a *expansão geralmente não inclui . Também for f in $(...) ...falha se qualquer nome de arquivo contém espaço em branco a menos que você defina IFS, pode falhar se qualquer nome de arquivo contém um caractere glob a menos que você defina -f / -o noglob e, dependendo do sistema ou shell, echopode falhar se qualquer nome de arquivo for hífen + letra ou contiver barra invertida. O OTOH ls -1 /path/to/dirpor si só imprime de forma confiável cada nome de arquivo em uma linha, modulo a diferença de dotfiles.
dave_thompson_085
0

se você quiser apenas o nome do arquivo:

for file in /home/user/*; do       
  f=$(echo "${file##*/}");
  filename=$(echo $f| cut  -d'.' -f 1); #file has extension, it return only filename
  echo $filename
done

para obter mais informações sobre o cutcomando, consulte aqui .

Josef
fonte