我有大约 3k + 个文件夹,它们可以包含两种类型的文件,一个 spring 文件和一对 fastq.gz 文件。我想扫描文件夹并了解目录中是否存在两个或其中一个文件扩展名 -
- 包含一对fastq.gz和spring文件
- 一个 fastq.gz 文件和 spring 文件
- 单个 Spring 文件
- 一对 fastq.gz 文件
- 单个 fastq.gz 文件
我使用了[ /path/to/dir/*fastq.gz ]
,但出现了unary operator expected
错误,而且使用[[ ]]
似乎无法正确测试。
我使用的实际脚本是 -
check_dir () {
in="$1"
echo "$in Checking for spring"
[ "$in"/*spring -f ] && echo "$in"
}
export -f check_dir
我正在使用 bash,任何有关逻辑的帮助都将不胜感激
答案1
unary operator expected
是因为[
和*
(在你的*fastq.gz
)中独立工作。
[
不是 shell 语法。[
是常规命令(Bash 中的内置命令,但仍然是命令)并且]
是它的最后一个命令争论,是强制性的。介于两者之间的任何内容也是一种争论。
shell/path/to/dir/*fastq.gz
在调用 之前会扩展为一个或多个单词[
。[
会将这些单词加上必需的单词]
视为参数。根据参数的数量及其内容,[
预计零个或多个参数将是运算符(例如-f
)。
如果扩展为单个参数,则您的[ /path/to/dir/*fastq.gz ]
命令将有效(请注意,“将有效”并不等同于“将执行您想要的操作”)。这包括不匹配任何内容的情况;传统上(在 Bash 中默认情况下)如果没有匹配,则将按原样处理。它可能会扩展到多个单词,其中没有一个看起来像操作员可以理解的。您收到的错误很可能来自模式扩展到两个单词的情况。/path/to/dir/*fastq.gz
*
/path/to/dir/*fastq.gz
/path/to/dir/*fastq.gz
[
后来你使用了[ "$in"/*spring -f ]
。这更糟糕,因为你可能想要类似[ -f some/path ]
where 的东西-f
is 的内容前测试路径。这仍然[ -f "$in"/*spring ]
不是一个可靠的修复,因为"$in"/*spring
一般来说可能会扩展到多个参数,并且[
不会支持它们。你写的是最多一个*spring
文件,所以你的情况像这样的代码可能会有用;但它仍然是糟糕的代码。
使用时[
,请勿使用*
可能扩展为多个单词的通配符;这会立即或很快失败。[[
内部结构有所不同但这对你的目的也没有好处。
你想知道一个模式有多少个文件/path/to/dir/*fastq.gz
。正确的做法是将扩展的结果赋给一个数组。可移植的数组只有一个:shell 脚本(或 shell 函数)的参数数组;您需要额外的代码来检测零匹配的情况(仍然会生成一个单词:未扩展的模式字符串)。您的问题被标记为狂欢,所以我将使用一个命名数组和一些其他不可移植的功能:
# non-portable code, works in Bash
check_dir () (
dir="${1-.}"
dir="${dir%/}/"
[ -d "$dir" ] || { echo "Not a directory." >&2; return 1; }
shopt -s nullglob
files=( "$dir"/*fastq.gz )
nf="${#files[@]}"
files=( "$dir"/*spring )
ns="${#files[@]}"
printf '%s\t%s\t%s\n' "$nf" "$ns" "$dir"
)
用法:check_dir path/to/dir
或check_dir
(默认路径为.
)。该函数将打印文件数*fastq.gz
、选项卡、文件数*spring
、选项卡,最后打印检查的路径(以结尾的 打印/
)。
现在您可以分析目录树(下面的函数需要定义上面的函数):
# non-portable code, works in Bash
check_dirs () (
dir="${1-.}"
dir="${dir%/}/"
[ -d "$dir" ] || { echo "Not a directory." >&2; return 1; }
shopt -s nullglob globstar
for d in "$dir"**/; do
check_dir "$d"
done
)
用法:check_dirs path/to/dir
或check_dirs
(默认路径为.
)。
笔记:
对于较大的目录树,
check_dirs
最初似乎会停滞。这是因为在调用并打印任何内容for d in "$dir"**/
之前,需要完全展开。check_dir
这些函数被刻意定义为子 shell(
check_dir () (
与 相对check_dir () {
),因此 shell 选项(shopt
)和所有变量都是本地的。如果您要
check_dir
计算隐藏文件的数量,您需要dotglob
此功能(即shopt -s nullglob dotglob
)。如果您想
check_dirs
进入隐藏目录,您需要dotglob
此功能(即shopt -s nullglob globstar dotglob
)。除非目录名称包含换行符,否则
check_dir
或的输出check_dirs
很容易用标准工具解析。有用的命令:sort -n
,,。grep $'^2\t1\t'
cut -f 3-
例如,查找
./
恰好有一个*fastq.gz
文件和恰好零个*spring
文件的目录:check_dirs | grep $'^1\t0\t' | cut -f 3-