1

我想处理包含单引号文件名的文本文件中的文件,例如

'new'$'\n''line'
'tab'$'\t''ulator'

手动处理此文件的复制和粘贴工作正常:

test -f 'tab'$'\t''ulator'


现在,使用 bash read 内置命令从文件中读取

while IFS="" read -r myfile; do
  line=$myfile
  ...
done < text.txt

给出包含转义单引号的字符串,例如

'\''new'\''$'\''\n'\'''\''line'\'''
'\''tab'\''$'\''\t'\'''\''ulator'\'''

但是,在 bash 脚本中处理此文件名不起作用。

test -f "$myfile"
test -f ${myfile}


如何在 bash 中禁用 /undo 转义单引号和处理原始文件名?

4

2 回答 2

2

使用eval

许多人相当合理地认为eval是邪恶的拼写错误。因此,我会将此解决方案视为仅在所有其他方法都失败时才使用的最后选择。

让我们来看看这个示例文件:

$ cat badformat
'new'$'\n''line'
'tab'$'\t''ulator'

我们可以读取和解释这些文件名,如下例所示:

while read -r f; do
    eval "f=$f"; [ -f "$f" ] || echo "file not found"
done <badformat

使用 NUL 分隔的文件名列表

Unix 文件名中唯一不能出现的字符是 NUL(十六进制 00)。因此,许多 Unix 工具被设计成能够处理 NUL 分隔的列表。

因此,在创建文件时,请替换:

stat -c %N * >badformat

和:

printf '%s\0' * >safeformat

后一个文件可以通过 while-read 循环读入 shell 脚本。例如:

while IFS= read -r -d $'\0' f; do
    [ -f "$f" ] || echo "file not found"
done <safeformat

除了 shell while-read 循环,请注意 , grep, find,sort以及xargsGNUsed和 GNUawk都具有处理 NUL 分隔列表的本机能力。因此,NUL 分隔列表方法既安全又得到很好的支持。

于 2016-07-19T21:42:13.627 回答
0

找到了字符串操作的解决方案

${filename//$'\047'\\$'\047'$'\047'/$'\047'}

正如你上面提到的,使用 eval 对于像“rm -rf”这样的文件名是非常危险的。关于 stat -c %N (仅转义单引号、换行符和制表符)还有另一种解决方案

while IFS="" read -r myfile; do

  filename="$myfile"

  filename="${filename#?}"
  filename="${filename%?}"
  filename="${filename//"'$'\t''"/$'\011'}"
  filename="${filename//"'$'\n''"/$'\012'}"
  filename="${filename//$'\047'\\$'\047'$'\047'/$'\047'}"

  test -f "$filename" && echo "$myfile exists"

done < text.txt
于 2016-07-19T21:32:50.357 回答