set '%s_q1.out %s_q2.out %s_q3.out\n'
:|for d in several directories
do cd -P -- "$d" || ! break
set "$1" "../${PWD##*/}"
{ sed -ne'\|\( \.\./a_a_q[123]\.out\)\{3\}|q;s/.//p'
printf "$@" "$2" "$2"; cut -c2-
} <<-IN >./infile
$(paste -d\ - ./infile)
IN
done
Isso deve funcionar com um POSIX sed
e um bash
, zsh
, ksh
, mksh
shell e muitos outros. Com um dash
ou yash
shell, o documento here provavelmente não terá um arquivo regular e, portanto, não é possível confiar na função lseek()
necessária para suportar o compartilhamento. Nesses casos, você deve mudar para uma das shells acima mencionadas.
Se você usar um GNU sed
, você vai querer usar sed -une
em vez de apenas sed -ne
.
Aqui está um resumo:
-
Primeiro, nós usaremos set
um argumento como a string de formato printf
repetidamente e definiremos ambos $PWD
e $OLDPWD
para .
-
Em seguida, iniciamos a iteração de itens em several directories
. Sejam eles diretórios ou links simbólicos reais, obtemos o nome de caminho canônico e -P
em $PWD
e set
do último componente de caminho para $2
.
-
A próxima coisa que acontece ocorre na parte inferior do redirecionamento heredoc. paste
lê todo o ./infile
para algum arquivo temporário seguro que o shell assegurou para nós enquanto prefixava um único espaço em cada linha. O shell então define esse arquivo temporário para stdin e ./infile
é novamente designado - mas desta vez como stdout.
-
sed
faz muito pouca edição. Até encontrar sua linha de correspondência, ele remove o primeiro caractere de cada linha e p
solicita os resultados. Uma vez que ele encontra sua linha, a entrada q
uits é totalmente - nada é impresso.
-
Mas printf
imprime ../${PWD##*/}_q[123].out
seguido por uma nova linha para stdout e depois cut
escolhe stdin em que sed
deixou (logo após a sua linha de correspondência) e lê o resto enquanto tira o primeiro byte de cada linha de entrada.
E assim todo o ./infile
editado acaba de volta de onde veio.
Oh, eu testei isso.
Substitui o bit several directories
pelo nome de caminho /tmp
e fiz ...
{ seq 7
echo '../a_a_q1.out ../a_a_q2.out ../a_a_q3.out'
seq 9 14
printf %s\n '' '' ''
} >/tmp/infile
... que escreveu um /tmp/infile
que parecia:
1
2
3
4
5
6
7
../a_a_q1.out ../a_a_q2.out ../a_a_q3.out
9
10
11
12
13
14
Depois de executar o snippet de código acima em /tmp
, embora ...
cat /tmp/infile
1
2
3
4
5
6
7
../tmp_q1.out ../tmp_q2.out ../tmp_q3.out
9
10
11
12
13
14