O problema é que os caminhos listados em ~ / files incluem escapes (barras invertidas) antes de espaços (e possivelmente outros caracteres), e estes são tratados como parte do nome do arquivo. Normalmente, quando você insere um comando como este:
stat -x ./2017\ Digital/redacted\ Projects-redacted-IP.idx
o processo de análise do shell interpreta as barras invertidas como significando que os espaços são parte do argumento (em vez de separadores entre argumentos), e depois os remove antes de passar o argumento para stat
. Assim, stat realmente recebe dois argumentos: -x
e ./2017 Digital/redacted Projects-redacted-IP.idx
.
Por outro lado, quando você lê os caminhos de arquivo a partir de um arquivo, ele nunca passa pela etapa de escape parse-and-remove, então as fugas são passadas para stat
como parte do argumento, e procura por arquivos que realmente tem barras invertidas em seus nomes (e não os encontra).
As citações não ajudarão com isso. O shell analisa (e remove) fugas, citações e tais antes substituindo valores variáveis, de modo que ele nunca acabe interpretando & removendo escapa e aspas de seus valores. (Bem, a menos que você use algo como eval
, mas não faça isso - isso abre caminho para muitas oportunidades para coisas novas darem errado.)
Acontece que há uma maneira fácil de fazer a análise de escape & remoção do conteúdo do arquivo. Em um comentário, eu recomendei mudar de um loop for
para um loop while read
e vincular BashFAQ # 1: Como eu posso ler um arquivo (fluxo de dados, variável) linha-a-linha (e / ou campo a campo)? . Se você leu isso, ele realmente recomenda usar while IFS= read -r
e diz:
The
-r
option toread
prevents backslash interpretation (usually used as a backslash newline pair, to continue over multiple lines or to escape the delimiters). Without this option, any unescaped backslashes in the input will be discarded. You should almost always use the-r
option withread
.
... exceto neste caso, você deseja que as barras invertidas sejam interpretadas e removidas ("descartadas"), por isso, desative o -r
. Ah, e depois coloque todas as referências de variáveis entre aspas duplas para evitar que elas sejam divididas em espaços (sem aspas duplas, a divisão acontece se os espaços tiverem ou não escape):
#!/bin/bash
i=0
while IFS= read j; do
stat -x "$j"
done <~/files