Então eu me deparei com um pouco de barreira, eu tenho uma opção no meu script que chama uma função que me permite especificar um arquivo/diretório e então eu quero analisar essa saída em uma ferramenta de menu (usando dmenu neste caso) para selecionar qual arquivo é o que eu quero especificamente e continuar trabalhando com essa seleção como uma variável no mesmo script. Isso funciona bem se for apenas um arquivo ou diretório, mas eu quero ser capaz de usar a opção várias vezes e então analisar toda essa saída de uma vez para dmenu. Aqui está um trecho
fileSelection () {
if [ -d "${OPTARG}" ]; then find "${OPTARG}" -type f; fi;
if [ -f "${OPTARG}" ]; then printf '%s\n' "${OPTARG}"; fi;
}
while getopts "f:" option; do
case "${option}" in
f) file="$(fileSelection|dmenu)";;
esac
done
E como eu disse, isso funciona se eu fizer:
myscript -f file
ou
myscript -f directory
mas eu esperava poder fazer isso também:
myscript -f file1 -f file2
O problema é que, como a função é chamada consecutivamente, não consigo analisar a saída no dmenu dessa forma, porque ele não invoca o dmenu com as opções file1 e file2, mas primeiro com file1 e depois com file2. Espero que isso faça sentido.
Pode haver alguma solução realmente simples que eu esteja esquecendo, pensei em simplesmente escrever a saída em um arquivo e então analisar isso, o que pode funcionar, mas gostaria de evitar o pipe para arquivos, se possível. Também estou tentando mantê-lo compatível com POSIX, e apreciaria respostas que sigam isso.
Você pode coletar os valores derivados de seu
-f
e passá-los todos juntos paradmenu
. Aqui está um exemplo que funcionará para a maioria dos diretórios e arquivos - mas não aqueles que contêm uma nova linha incorporada:Já que você quer uma solução POSIX, e já está assumindo que nomes de arquivo não podem conter quebras de linha, você pode construir uma única sequência de valores terminados em quebra de linha e usá-la. Na verdade, neste caso eu provavelmente construiria o conjunto de pontos de partida e então usaria
find | dmenu
entre eles em vez de construir o conjunto de resultados como fiz na minha primeira abordagem.Você
fileSelection|dmenu
pressupõe que os caminhos dos arquivos não contêm caracteres de nova linha, então você pode criar$file
uma lista separada/delimitada por nova linha:Uma alternativa é gerar o
set -- ...
código shell para definir a lista de parâmetros posicionais para a lista de arquivosPOSIXly, isso ainda é perigoso, pois
sed
não é necessário para funcionar corretamente com linhas que excedam LINE_MAX bytes de comprimento e não há garantia de que a saídafind
tenha linhas tão curtas (nem mesmo menores que o próprio PATH_MAX, não há garantia de que seja menor que o LINE_MAX).Faça com que a opção de análise
while
-loop produza os nomes encontrados e passe a saída dele paradmenu
. Ou seja, mova o piping paradmenu
da saída defileSelection
para a saída dowhile
-loop.Para fazer isso corretamente, primeiro precisamos ter certeza de que realmente há pelo menos uma
-f
opção na linha de comando. Isso significa ter que analisar as opções duas vezes: uma para manipular qualquer outra opção e detectar um-f
, e mais uma vez para agir nas-f
opções e obter a lista de arquivos e deixar o usuário escolher filename em nossafile
variável.Talvez eu tenha encontrado uma solução depois de analisar mais a fundo a maneira POSIX de fazer matrizes
esta é uma versão muito simplificada do script, mas simplesmente analisar de sed para dmenu deve produzir o que eu quero. Vou verificar novamente quando estiver em casa. Obrigado a Chris Davies por me apontar a direção certa.