Respostas:
No GNU findvocê pode usar -printfparâmetros para isso, por exemplo:
find /dir1 -type f -printf "%f\n"
-otem precedência menor do que implícita -a, por isso muitas vezes você vai querer agrupar seus -oargumentos)
Se a sua localização não tiver a opção -printf, você também poderá usar o nome da base:
find ./dir1 -type f -exec basename {} \;
... {} ';'
Use o -execdirque mantém automaticamente o arquivo atual {}, por exemplo:
find . -type f -execdir echo '{}' ';'
Você também pode usar em $PWDvez de .(em alguns sistemas, isso não produzirá um ponto extra na frente).
Se você ainda tiver um ponto extra, alternativamente, poderá executar:
find . -type f -execdir basename '{}' ';'
-execdir utility [argument ...] ;O
-execdirprimário é idêntico ao-execprimário, com a exceção de que o utilitário será executado a partir do diretório que contém o arquivo atual .
Quando usado em +vez de ;, {}é substituído por tantos nomes de caminho quanto possível para cada chamada de utilitário. Em outras palavras, ele imprimirá todos os nomes de arquivos em uma linha.
./filenamevez de filename. Dependendo das suas necessidades, pode ou não estar bem.
$PWDvez de ..
Se você estiver usando o GNU find
find . -type f -printf "%f\n"
Ou você pode usar uma linguagem de programação como Ruby (1.9+)
$ ruby -e 'Dir["**/*"].each{|x| puts File.basename(x)}'
Se você gosta de uma solução bash (pelo menos 4)
shopt -s globstar
for file in **; do echo ${file##*/}; done
Se você deseja executar alguma ação somente contra o nome do arquivo, basenamepode ser difícil usá- lo.
Por exemplo, isto:
find ~/clang+llvm-3.3/bin/ -type f -exec echo basename {} \;
apenas ecoará o nome da base /my/found/path. Não é o que queremos se queremos executar o nome do arquivo.
Mas você pode então xargsa saída. por exemplo, para matar os arquivos em um diretório com base nos nomes em outro diretório:
cd dirIwantToRMin;
find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \; | xargs rm
find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \;
-exece -execdirsão lentos, xargsé rei.
$ alias f='time find /Applications -name "*.app" -type d -maxdepth 5'; \
f -exec basename {} \; | wc -l; \
f -execdir echo {} \; | wc -l; \
f -print0 | xargs -0 -n1 basename | wc -l; \
f -print0 | xargs -0 -n1 -P 8 basename | wc -l; \
f -print0 | xargs -0 basename | wc -l
139
0m01.17s real 0m00.20s user 0m00.93s system
139
0m01.16s real 0m00.20s user 0m00.92s system
139
0m01.05s real 0m00.17s user 0m00.85s system
139
0m00.93s real 0m00.17s user 0m00.85s system
139
0m00.88s real 0m00.12s user 0m00.75s system
xargsO paralelismo de também ajuda.
Curiosamente, não posso explicar o último caso de xargssem -n1. Dá o resultado correto e é o mais rápido¯\_(ツ)_/¯
( basenamepega apenas um argumento de caminho, mas xargsenvia todos eles (na verdade, 5000) sem -n1. não funciona no linux e no openbsd, apenas no macOS ...)
Alguns números maiores de um sistema Linux para ver como -execdirajuda, mas ainda muito mais lento que um paralelo xargs:
$ alias f='time find /usr/ -maxdepth 5 -type d'
$ f -exec basename {} \; | wc -l; \
f -execdir echo {} \; | wc -l; \
f -print0 | xargs -0 -n1 basename | wc -l; \
f -print0 | xargs -0 -n1 -P 8 basename | wc -l
2358
3.63s real 0.10s user 0.41s system
2358
1.53s real 0.05s user 0.31s system
2358
1.30s real 0.03s user 0.21s system
2358
0.41s real 0.03s user 0.25s system
find, é -execdirque se torna o mais rápido, pois a criação de novos processos é uma operação relativamente cara.
Como outros já apontaram, você pode combinar finde basename, mas, por padrão, o basenameprograma funcionará apenas em um caminho de cada vez; portanto, o executável precisará ser iniciado uma vez para cada caminho (usando um find ... -execou outro find ... | xargs -n 1), o que pode ser lento.
Se você usar a -aopção basename, ela poderá aceitar vários nomes de arquivos em uma única invocação, o que significa que você poderá usar xargssem o -n 1para agrupar os caminhos em um número muito menor de invocações basename, o que deve ser mais eficiente.
Exemplo:
find /dir1 -type f -print0 | xargs -0 basename -a
Aqui eu incluí o -print0e -0(que deve ser usado em conjunto), a fim de lidar com qualquer espaço em branco dentro os nomes de arquivos e diretórios.
Aqui está uma comparação de tempo, entre as versões xargs basename -ae xargs -n1 basename. (Para uma comparação do tipo com o mesmo, os tempos relatados aqui são após uma execução fictícia inicial, para que sejam feitos após os metadados do arquivo já terem sido copiados no cache de E / S.) Canalizei a saída para cksumnos dois casos, apenas para demonstrar que a saída é independente do método usado.
$ time sh -c 'find /usr/lib -type f -print0 | xargs -0 basename -a | cksum'
2532163462 546663
real 0m0.063s
user 0m0.058s
sys 0m0.040s
$ time sh -c 'find /usr/lib -type f -print0 | xargs -0 -n 1 basename | cksum'
2532163462 546663
real 0m14.504s
user 0m12.474s
sys 0m3.109s
Como você pode ver, é realmente muito mais rápido evitar o lançamento basenametodas as vezes.
basenameaceitará vários nomes de arquivos sem precisar de argumentos adicionais na linha de comando. O uso -aaqui é no Linux. ( basename --versionme diz basename (GNU coreutils) 8.28.)