Digamos, eu tenho um arquivo foo.txt
especificando N
argumentos
arg1
arg2
...
argN
que eu preciso passar para o comando my_command
Como uso as linhas de um arquivo como argumentos de um comando?
Digamos, eu tenho um arquivo foo.txt
especificando N
argumentos
arg1
arg2
...
argN
que eu preciso passar para o comando my_command
Como uso as linhas de um arquivo como argumentos de um comando?
Respostas:
Se seu shell é bash (entre outros), um atalho para
$(cat afile)
é$(< afile)
, então você deve escrever:Documentado na página de manual do bash na seção 'Substituição de comando'.
Em alternativa, leia seu comando a partir de stdin, portanto:
mycommand < file.txt
fonte
<
operador. Isso significa que o próprio shell executará o redirecionamento em vez de executar ocat
binário por suas propriedades de redirecionamento."$(…)"
, sem , o conteúdo defile.txt
seria passado para a entrada padrão demycommand
, não como argumento."$(…)"
significa executar o comando e devolver a saída como uma string ; aqui o "comando" lê apenas o arquivo, mas poderia ser mais complexo.Como já mencionado, você pode usar os backticks ou
$(cat filename)
.O que não foi mencionado, e acho importante notar, é que você deve se lembrar que o shell separará o conteúdo desse arquivo de acordo com o espaço em branco, fornecendo cada "palavra" encontrada ao seu comando como argumento. E embora você possa incluir um argumento da linha de comando entre aspas, para que ele possa conter espaços em branco, seqüências de escape etc., a leitura do arquivo não fará a mesma coisa. Por exemplo, se o seu arquivo contiver:
os argumentos que você receberá são:
Se você deseja extrair cada linha como argumento, use a construção while / read / do:
fonte
read -r
menos que você queira expandir as seqüências de escape de barra invertida - e NUL é um delimitador mais seguro para usar do que a nova linha, principalmente se os argumentos que você está passando são coisas como nomes de arquivos, que podem conter novas linhas literais. Além disso, sem limpar o IFS, você obtém o espaço em branco inicial e final implicitamente limpoi
.passará o conteúdo do arquivo para o comando stdin, mas removerá as novas linhas, o que significa que você não pode repetir cada linha individualmente. Para isso, você pode escrever um script com um loop 'for':
Ou (a variante de várias linhas):
Ou (variante de várias linhas com em
$()
vez de``
):Referências:
fonte
< file
backticks significa que ele realmente não executa um redirecionamentocommand
.command `< file`
Não funcionam no bash ou no POSIX sh; zsh é uma questão diferente, mas esse não é o shell sobre o qual esta questão se refere).Hello World
em uma linha. Você verá a primeira execuçãosome_command Hello
, entãosome_command World
, nãosome_command "Hello World"
ousome_command Hello World
.Você faz isso usando backticks:
fonte
echo "Hello * Starry * World" > file.txt
na primeira etapa, obteria pelo menos quatro argumentos separados passados para o segundo comando - e provavelmente mais, como os*
s se expandem para os nomes dos arquivos presentes no diretório atual.fork()
desabilitando um subshell com um FIFO anexado ao seu stdout, invocando/bin/cat
como filho desse subshell e lendo a saída através do FIFO; compare to$(<file.txt)
, que lê o conteúdo do arquivo no bash diretamente, sem subshells ou FIFOs envolvidos.Se você deseja fazer isso de uma maneira robusta que funcione para todos os argumentos de linha de comando possíveis (valores com espaços, valores com novas linhas, valores com caracteres de aspas literais, valores não imprimíveis, valores com caracteres globais, etc.), fica um pouco mais interessante.
Para gravar em um arquivo, com uma matriz de argumentos:
... substituir com
"argument one"
,"argument two"
etc., conforme apropriado.Para ler esse arquivo e usar seu conteúdo (no bash, ksh93 ou em outro shell recente com matrizes):
Para ler esse arquivo e usar seu conteúdo (em um shell sem matrizes; observe que isso substituirá sua lista de argumentos da linha de comando local e, portanto, é melhor executá-lo dentro de uma função, de modo que você substitua os argumentos da função e não a lista global):
Observe que
-d
(permitir que um delimitador de final de linha diferente seja usado) é uma extensão não POSIX, e um shell sem matrizes também pode não suportá-lo. Nesse caso, pode ser necessário usar uma linguagem não shell para transformar o conteúdo delimitado por NUL em umeval
formato seguro:fonte
Aqui está como passo o conteúdo de um arquivo como argumento para um comando:
fonte
$(<bar.txt)
(ao usar um shell, como o bash, com a extensão apropriada).$(<foo)
é um caso especial: diferentemente da substituição regular de comandos, como usada$(cat ...)
, ela não utiliza um subshell para operar e, assim, evita uma grande sobrecarga.Se tudo o que você precisa fazer é transformar o arquivo
arguments.txt
com o conteúdopara
my_command arg1 arg2 argN
então você pode simplesmente usarxargs
:Você pode colocar argumentos estáticos adicionais na
xargs
chamada, como oxargs -a arguments.txt my_command staticArg
que chamarámy_command staticArg arg1 arg2 argN
fonte
No meu shell bash, o seguinte funcionou como um encanto:
onde input_file é
Como é evidente, isso permite que você execute vários comandos com cada linha de input_file, um pequeno truque que aprendi aqui .
fonte
$(somecommand)
, esse comando será executado em vez de ser transmitido como texto. Da mesma forma,>/etc/passwd
será processado como um redirecionamento e substituição/etc/passwd
(se executado com permissões apropriadas) etc.xargs -d $'\n' sh -c 'for arg; do command1 "$arg"; command2 "arg"; command3 "arg"; done' _
- e também mais eficiente, pois passa o maior número possível de argumentos para cada shell possível, em vez de iniciar um shell por linha no seu arquivo de entrada.cat
Depois de editar a resposta de @Wesley Rice algumas vezes, decidi que minhas alterações estavam ficando grandes demais para continuar alterando sua resposta em vez de escrever a minha. Então, eu decidi que preciso escrever o meu!
Leia cada linha de um arquivo e opere linha por linha assim:
Isto vem diretamente do autor Vivek Gite aqui: https://www.cyberciti.biz/faq/unix-howto-read-line-by-line-from-file/ . Ele recebe o crédito!
E agora, para responder a essa pergunta agora fechada, que eu também tinha: É possível `git add` uma lista de arquivos de um arquivo?- aqui está a minha resposta:
Observe que
FILES_STAGED
é uma variável que contém o caminho absoluto para um arquivo que contém várias linhas em que cada linha é um caminho relativo para um arquivo que eu gostaria de fazergit add
. Este trecho de código está prestes a se tornar parte do arquivo "eRCaGuy_dotfiles / useful_scripts / sync_git_repo_to_build_machine.sh" neste projeto, para permitir a sincronização fácil de arquivos em desenvolvimento de um PC (por exemplo: um computador que eu codifique) para outro (por exemplo: computador mais poderoso em que construí): https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles .Referências:
Palavras-chave:
git add
-lo: É possível `git add` uma lista de arquivos de um arquivo?fonte