我刚开始学习Bash脚本并写了一些东西:
#!bin/bash
for str in stra strb strc
do
find . -name "*${str}*" | sort | cut -c3- > "${str}.list"
done
正如您所看到的,我正在尝试创建三个文件(“stra.list”,“strb.list”和“strc.list”),这些文件将列出包含“stra”,“strb”的文件的名称“,或”strc“分别在当前目录中。 cut -c3-
hack仅用于在查找结果的开头删除路径名./
。
但我现在所有的脚本都在创建三个空文件......
所以当我跑
时for str in stra strb strc;
do
echo "find .-name "*${str}*" | sort | cut -c3- > "${str}.list"";
done
我只看到
find .-name *stra* | sort | cut -c3- > stra.list
find .-name *strb* | sort | cut -c3- > strb.list
find .-name *strc* | sort | cut -c3- > strc.list
那么如何在扩展后保留包含变量的表达式周围的引号?我尝试添加一组额外的引号以及使用eval
,但似乎都不起作用。
更新: 我要问的是我如何编写我的find命令,以便Bash能够成功生成带有目标文件名的三个列表,而不是出于任何原因只创建三个空白列表。对此感到抱歉。
答案 0 :(得分:1)
如果您的目标是生成有效的shell命令,那么只是尝试保留引号是错误的(从某种意义上说它实际上是不安全的;恶意生成的变量内容可以执行shell注入攻击)。相反,告诉shell本身为要保留的内容生成有效的引用; printf %q
将在bash中执行此操作。
此特定变体需要足够新的bash才能拥有printf -v
。
#!/bin/bash
for str in stra strb strc; do
printf -v start '%q ' find . -name "*${str}*"
printf -v end '%q ' "${str}.list"
printf '%s\n' "$start | sort | cut -c3- >$end"
done
相比之下,如果您只是想修复原始脚本中的错误,假设您有GNU find
:
#!/bin/bash
for str in stra strb strc; do
find . -maxdepth 1 -name "*${str}*" -printf '%P\n' | sort > "${str}.list"
done
find
操作-printf '%P\n'
打印没有起始目录的名称,这意味着不需要删除./
。
因为你说你只是在当前目录中寻找文件,顺便说一下,这整个混乱都是过度的。你根本不需要find
。
for str in stra strb strc; do
files=( *"$str"* )
[[ -e $files ]] && printf '%s\n' "${files[@]}" >"$str.list"
done
请注意,如果您的任何文件名包含文字换行符,则此命令的输出可能会产生误导。 (出于这个原因,将文件名存储在换行符分隔的文件中是个坏主意)。
答案 1 :(得分:0)
有两种方法:
用单引号而不是双引号括起你的echo输出:
echo 'find .-name "*${str}*" | sort | cut -c3- > "${str}.list"';
或在内部引号前添加\
(反斜杠):
echo "find .-name \"*${str}*\" | sort | cut -c3- > \"${str}.list\"";