Você pode remover a substring de entrelinha mais curta que corresponde a */
tmp="${filename#*/}"
e, em seguida, remova a substring posterior mais longa que corresponda a /*
echo "${tmp%%/*}"
Posso usar a substituição de variáveis bash para extrair uma parte de uma variável baseada em um delimitador? Estou tentando obter o nome do diretório imediato de um nome de arquivo (neste caso, foo
).
$ filename=./foo/bar/baz.xml
Eu sei que posso fazer algo como
echo $filename | cut -d '/' -f 2
ou
echo $filename | awk -F '/' '{print $2}'
mas está ficando lento para bifurcar awk
/ cut
para vários nomes de arquivos.
Eu fiz um pequeno perfil das várias soluções, usando meus arquivos reais:
echo | corte:
real 2m56.805s
user 0m37.009s
sys 1m26.067s
echo | awk:
real 2m56.282s
user 0m38.157s
sys 1m31.016s
@ substituição de variáveis / expansão de parâmetros shell da steeldriver:
real 0m0.660s
user 0m0.421s
sys 0m0.235s
@ Disputas IFS do jai_s:
real 1m26.243s
user 0m13.751s
sys 0m28.969s
Ambas as sugestões foram uma grande melhoria em relação às minhas ideias existentes, mas a substituição de variáveis é mais rápida porque não requer nenhum processo novo.
echo $f
a/b/c
$ (IFS='/';set $f; echo $1)
a
$ (IFS='/';set $f; echo $2)
b
$ (IFS='/';set $f; echo $3)
c
com curinga, parece funcionar com aspas duplas ou simples -
f="a?b?c"
$(IFS="?"; set $f; echo $1)
a
echo $f
a*b*c
(IFS="*"; set $f; echo $1)
a
sim, você terá que desmarcar o IFS de volta ao padrão
unset IFS
Alimente a lista com awk
para agilizar:
awk -F '/' '{print $2}' < <(find /usr)
awk -F '/' '{print $2}' < inputfile
Demonstração:
time awk -F '/' '{print $2; SUM++} END {print "number of directories found: " SUM}' < <(find /usr -type d)
usr
usr
.
.
number of directories found: 16748
real 0m8.910s
user 0m0.050s
sys 0m0.050s
Por que você não usa o comando "dirname", em vez de todo esse material do awk / sed / cut?
filename=./foo/bar/baz.xml
dirname $filename
Rendimentos:
./foo/bar