Exportar d , depois estará disponível no seu script bash inline. Você também não precisa de bash aqui. Seu (espero que mais magro / mais rápido) sh também funcionaria. Além disso, você não precisa executar um shell por arquivo. Você pode enviar mais arquivos para seu script in-line com a variante -exec cmd {} + :
d=/tmp/foo
export d
find "$d" -type f -exec sh -c '
for file do
relative=${file#"$d/"}
dir=${file%/*}
relative_dir=${relative%/*}
relative_dir=${relative_dir:-.}
printf "%10s: %s\n" full "$file" \
relative "$relative" \
dir "$dir" \
reldir "$relative_dir"
done' sh {} +
O que dá:
full: /tmp/foo/bar/can/haz/bzr.txt
relative: bar/can/haz/bzr.txt
dir: /tmp/foo/bar/can/haz
reldir: bar/can/haz
Mas se você precisar apenas do caminho relativo, pode ser mais simples fazer isso:
(cd -P -- "$d" && find . -exec sh -c 'for file do...' sh {} +)
Isso também faria com que os argumentos de comando passassem para sh mais curto, então permitiria que find passasse mais argumentos para sh .
Note que não há nada específico para o GNU no seu comando find nem no meu. Isso deve funcionar em qualquer implementação find compatível com POSIX, não apenas na GNU. A única parte não POSIX em sua pergunta era obviamente bash e o operador ${1:offset} que é um operador de shell Korn, não em POSIX sh .
Para uma pesquisa de arquivos recursiva que permite especificar o tipo de arquivo, consulte também zsh :
(cd -P -- "$d" &&
for file (**/*(ND.)) {
dir=$file:h
printf '%10s: %s\n' relative $file reldir $dir
})
Acima, o . é equivalente a find -type f (somente arquivos regulares), enquanto D também inclui os ocultos, como find .
Como uma nota secundária, no caso geral:
c=$a$b; d=${c:${#a}}
[ "$b" = "$d" ] && echo yes
Não é garantido a saída "sim", porque os operadores ${#var} e ${var:offset} trabalham com caracteres , não bytes .
Por exemplo, em uma localidade UTF-8, ela não emitirá "sim" com esses valores de a e b :
a=$'St\xc3' b=$'\xa9phane'
Com esses, $c conteria meu primeiro nome ( Stéphane ) $a contém metade desse é caractere e $b a outra metade, ${#a} seria 3 (2 caracteres e 1 byte não formando um caracter válido, mas ainda é contado).
Então $d seria phane , não $'\xa9phane' .
No caso específico de d=$a/$b , ele deve estar OK, já que nenhum conjunto de caracteres geralmente disponível em localidades do sistema teria um caractere diferente de / que contém a codificação de / .