禁用从bash读取内置命令

时间:2016-07-19 20:24:53

标签: bash shell single-quotes

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

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

copy&用于手动处理此文件的粘贴工作正常:

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


现在,用bash读取文件读取内置命令

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中处理原始文件名?

2 个答案:

答案 0 :(得分:2)

使用eval

许多人非常合理地考虑eval as a mis-spelling of evil。 所以,我认为这个解决方案只有在其他所有方法都失败时才能使用。

我们来看看这个样本文件:

$ 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循环外,请注意grepfindsortxargs以及GNU sed和GNU { {1}},都具有处理NUL分隔列表的本机能力。因此,NUL分离列表方法既安全又受到良好支持。

答案 1 :(得分:0)

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

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

如上所述,使用eval对文件名非常危险,例如&rm -rf&#39;。关于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