Bash 使用嵌入换行符的mkdir-v输出

Bash 使用嵌入换行符的mkdir-v输出,bash,Bash,首先,这个问题纯粹是理论性的;它包括创建一个带有换行符的目录,这是一件永远不应该做的事情 也就是说,我试图使用mkdir-pvoutput删除脚本中特定时刻创建的目录,但只删除新创建的目录,而不是以前存在的目录 命令mkdir-pv将在此命令调用之前为不存在的每个目录打印一行,以便我可以重新注入rm-rf命令。它工作正常,除了目录包含换行符的情况,我看不出它有什么问题 我最简单的工作示例: declare -a created # Delete previous traces mkdir_out

首先,这个问题纯粹是理论性的;它包括创建一个带有换行符的目录,这是一件永远不应该做的事情

也就是说,我试图使用
mkdir-pv
output删除脚本中特定时刻创建的目录,但只删除新创建的目录,而不是以前存在的目录

命令
mkdir-pv
将在此命令调用之前为不存在的每个目录打印一行,以便我可以重新注入
rm-rf
命令。它工作正常,除了目录包含换行符的情况,我看不出它有什么问题

我最简单的工作示例:

declare -a created
# Delete previous traces
mkdir_out=$(mkdir -pv 'new 10'{1,2,3,$'\n',"'a",4})

# Convert to array
IFS=$'\n' read -d '' -a created < <(printf '%s' "${mkdir_out}")

# Debug
printf '=>[1] %s\n' "${created[@]}"

# We only want content between first and last quote
created=( "${created[@]%[\'\"]}" )
created=( "${created[@]#*[\'\"]}" )

# Debug
printf '=>[2] %s\n' "${created[@]}"

rm -rfv "${created[@]}"
ls  # Directory "new 10\n" is still there!!
declare-a已创建
#删除以前的跟踪
mkdir_out=$(mkdir-pv'new 10'{1,2,3,$'\n','a',4})
#转换为数组
IFS=$'\n'read-d'-a created<[2]%s\n'${created[@]}
rm-rfv“${created[@]}”
ls#目录“新10\n”仍然存在!!

那么,安全的方法是什么呢?

像mkdir:created directory'foo'这样的输出只适用于人类。不要试图解析它

如果您想处理所有可能的文件名,而无法处理
\0
分隔列表,则必须逐个处理。下面是一个例子:

declare -a created dirs

dirs=( 'new 10'{1,2,3,$'\n',"'a",4} )

created=()
for dir in "${dirs[@]}"
do
  if [[ ! -d "$dir" ]] && mkdir -p "$dir"
  then
    created+=( "$dir" )
  fi
done

rm -rfv "${created[@]}"
ls  # Directory "new 10\n" is not there.

类似于
mkdir:created directory'foo'
的输出仅适用于人类。不要试图解析它

如果您想处理所有可能的文件名,而无法处理
\0
分隔列表,则必须逐个处理。下面是一个例子:

declare -a created dirs

dirs=( 'new 10'{1,2,3,$'\n',"'a",4} )

created=()
for dir in "${dirs[@]}"
do
  if [[ ! -d "$dir" ]] && mkdir -p "$dir"
  then
    created+=( "$dir" )
  fi
done

rm -rfv "${created[@]}"
ls  # Directory "new 10\n" is not there.

这不是换行符,这是一个文字
\n
“我正试图使用mkdir-pv输出来删除”,为什么,请使用传递给
mkdir
的参数。对不起@Josh lee,你是对的,我粘贴了错误的mkdir参数。编辑:嗨,@Dzienny。如果我使用与
mkdir
相同的参数,rm将删除我的所有目录:脚本创建的目录和已经创建的目录;问题在于假设永远不会使用换行符的代码。早期的shell在设计上做了一个折衷,在某些情况下使键入命令尽可能简单,但代价是很难正确处理所有情况。几十年后,我们仍在为这一决定付出代价。即使你不希望使用这样的名称,你的代码仍然应该对意外或故意使用它们的“对手”具有弹性。这不是一句新语,这是一个字面意思
\n
“我正试图使用mkdir-pv输出来删除”,为什么,使用你传递给
mkdir
的参数呢。对不起@Josh lee,你是对的,我粘贴了错误的mkdir参数。编辑:嗨,@Dzienny。如果我使用与
mkdir
相同的参数,rm将删除我的所有目录:脚本创建的目录和已经创建的目录;问题在于假设永远不会使用换行符的代码。早期的shell在设计上做了一个折衷,在某些情况下使键入命令尽可能简单,但代价是很难正确处理所有情况。几十年后,我们仍在为这一决定付出代价。即使您不希望使用这样的名称,您的代码仍然应该能够抵御意外或故意使用它们的“对手”。酷,这将是我的第一选择。出于好奇,有没有办法“重新转义”或解析输出中的换行符?没有好的标准方法,但是
bash
提供了两种方法。第一种是将
%q
格式与
printf
一起使用;第二个(最近在4.4中引入)是使用
${foo@Q}
作为参数扩展。酷,这将是我的第一选择。出于好奇,有没有办法“重新转义”或解析输出中的换行符?没有好的标准方法,但是
bash
提供了两种方法。第一种是将
%q
格式与
printf
一起使用;第二个(最近在4.4中引入)是使用
${foo@Q}
作为参数展开。