Shell Linux/sh:如何仅列出文件夹中的文件(使用witespace)并将其保存到一行中的变量中
我尝试获取该格式的文件列表(使用witespaces): “file1.html”“file 2.php”“file_3.php” 输出:Shell Linux/sh:如何仅列出文件夹中的文件(使用witespace)并将其保存到一行中的变量中,shell,printf,sh,whitespace,7zip,bash,Shell,Printf,Sh,Whitespace,7zip,Bash,我尝试获取该格式的文件列表(使用witespaces): “file1.html”“file 2.php”“file_3.php” 输出: "/volume1/web/.htaccess" "/volume1/web/file.html" "/volume1/web/a b.php" 输出非常完美,但是。。。如何将此输出放入变量? 我这样做 IFS=$'\n' for file in $(find "${WEB_DIR}" -mindepth 1 -maxdepth 1 -type f) ;
"/volume1/web/.htaccess" "/volume1/web/file.html" "/volume1/web/a b.php"
输出非常完美,但是。。。如何将此输出放入变量?
我这样做
IFS=$'\n'
for file in $(find "${WEB_DIR}" -mindepth 1 -maxdepth 1 -type f) ; do
mystring+=$(printf "\"$file\" ")
done
echo ${mystring}
在输出中,我有:
tmp.sh: line 48: mystring+="/volume1/web/.htaccess" : not found
注:
- 下面的答案接受了问题的前提:使用双引号文件路径列表构建单个字符串值,如问题中所示(
)“/volume1/web/.htaccess”“/volume1/web/file.html”“/volume1/web/ab.php”
- 但是,OP最终希望将该字符串作为另一个命令的一部分使用,这是行不通的,因为当您引用字符串变量时,嵌入的双引号不再被识别为标识单独参数的字符串分隔符
- 正确的解决方法是使用
(在本例中)或通常使用查找-exec…+
将文件名列表作为操作数(参数)传递给另一个命令;e、 例如,要将文件名传递给命令xargs
(foo
严格传递所有文件路径,无论它们是否包含空格):{}
find“${WEB_DIR}”-mindepth 1-maxdepth 1-type f-exec foo-bar{}+
- 如果文件名列表不在目标命令行的末尾,则需要一个中间的
命令:sh-c
find“${WEB_DIR}”-mindepth 1-maxdepth 1-type f-exec sh-c'foo-bar“$@”-baz'-{}+
- 正确的解决方法是使用
您已经标记了您的问题,但是您的shebang行目标,其中的Bash扩展不能保证可用 在您的情况下(听起来您正在使用
dash
,它在Ubuntu上充当/bin/sh
):
- ANSI C带引号的字符串,如
不可用-$'\n'
扩展为文字$'\n'
$\n
- 这意味着这3个文字字符中的任何一个
,$
或\
用作字段分隔符-在您的情况下,这恰好起作用,因为文件路径恰好不包含这些字符n
- 这意味着这3个文字字符中的任何一个
- 运算符
无法识别-整个令牌+=
被视为命令名,这会导致您看到的错误mystring+=“/volume1/web/.htaccess”
- 如果确实要以Bash为目标,请替换
和#/bin/sh
#/bin/bash
- 请注意,要使
代码完全健壮,除了设置bash
之外,还应关闭globbing($IFS
)李>set+f
- 您的代码可以简化-请参阅下文
- 请注意,要使
- 如果不是(如果您的代码必须是可移植的),您必须找到与POSIX兼容的替代方案-请参阅下文
这里有一个便携式解决方案(适用于任何兼容POSIX的
sh
):
使用(
的bash
等价物,我不太清楚为什么我们要麻烦使用变量的中间步骤:
find "${WEB_DIR}" -mindepth 1 -maxdepth 1 -type f -print0 | xargs -0 /usr/syno/bin/7z \
a "${BACKUP_DIR}/backup_webfiles_${TIMESTAMP}.7z" -xr!thumbs.db -xr!@eaDir -xr!@tmp \
-xr!#recycle -xr!lost+found -xr!.DS_Store -t7z -m0=lzma2 -ms=off -mhe -mmt -mx9 \
-v${SPLIT_VOLUME} -p"${PASSWORD}"
我不确定您是否必须告诉7z文件来自stdin,因此您可能必须在“${only_files}”处添加连字符(-)过去是???OP的后续问题被错误地作为答案发布,删除后,您的答案的上下文丢失。您对中间变量的看法是正确的。它不仅没有必要,而且不起作用。通常,您不需要使用xargs
和查找,因为-exec
操作c直接调用命令。7z
作为xargs
目标命令,不会通过stdin接收文件名;相反,xargs
将它们作为参数列表传递到命令行末尾。
while IFS= read -r file; do
mystring="$mystring$(printf "\"$file\" ")"
done <<EOF
$(find "${WEB_DIR}" -mindepth 1 -maxdepth 1 -type f)
EOF
echo "$mystring"
IFS= read -r mystring <<EOF
$(find "${WEB_DIR}" -mindepth 1 -maxdepth 1 -type f -exec printf '"%s" ' {} +)
EOF
echo "$mystring"
IFS= read -r mystring < \
<(find "${WEB_DIR}" -mindepth 1 -maxdepth 1 -type f -exec printf '"%s" ' {} +)
echo "$mystring"
IFS= read -r mystring < <(find "${WEB_DIR}" -mindepth 1 -maxdepth 1 -type f -printf '"%p" ')
echo "$mystring"
find "${WEB_DIR}" -mindepth 1 -maxdepth 1 -type f -print0 | xargs -0 /usr/syno/bin/7z \
a "${BACKUP_DIR}/backup_webfiles_${TIMESTAMP}.7z" -xr!thumbs.db -xr!@eaDir -xr!@tmp \
-xr!#recycle -xr!lost+found -xr!.DS_Store -t7z -m0=lzma2 -ms=off -mhe -mmt -mx9 \
-v${SPLIT_VOLUME} -p"${PASSWORD}"