【问题标题】:find emitting unexpected ".", making wc -l list more contents than expected发现发出意外的“。”,使 wc -l 列出比预期更多的内容
【发布时间】:2016-03-30 09:04:40
【问题描述】:

我正在尝试使用较新的命令,如下所示:

touch $HOME/mark.start -d "$d1"
touch $HOME/mark.end -d "$d2"
SF=$HOME/mark.start
EF=$HOME/mark.end
find . -newer $SF ! -newer $EF

但这给了我这样的输出:

.
./File5

并将其计为 2 个文件,但是该目录只有 1 个文件,即 File5。为什么会发生这种情况以及如何解决?

更新

我实际上是在尝试运行以下脚本:

#!/bin/bash
check_dir () {
  d1=$2
  d2=$((d1+1))
  f1=`mktemp`
  f2=`mktemp`
  touch -d $d1 $f1
  touch -d $d2 $f2
  n=$(find $1 \( -name "*$d1*" \) -o \( -newer $f1 ! -newer $f2 \) | wc -l)
  if [ $n != $3 ]; then echo $1 "=" $n ; fi
  rm -f $f1 $f2
}

这会检查目录中是否包含具有特定日期(格式为 YYYMMDD)的文件,或者其上次修改时间是否为最近 1 天。

check_dir ./dir1 20151215 4
check_dir ./dir2 20151215 3

在 dir1 中应该有 4 个这样的文件,如果不是真的,那么它将打印那里的实际文件数。

因此,当目录中只有名称中包含日期的文件时,它会很好地检查它们,但是当它检查较新的文件时,它总是会额外提供 1 个文件(甚至目录中都不存在)。为什么会这样???

【问题讨论】:

  • 这是一个非常好的开始测试用例。也许您可以设置 d1 和 d2 值,并在它们之间的某个位置创建一个文件以拥有一个完全独立的复制器? (也许在 $HOME 以外的地方创建内容以便于清理?)
  • 另外,与您的实际问题无关,这里有一堆引用错误;请参阅shellcheck.net 以自动检测相同的内容。
  • 另外,这里有很多不可移植的用法,所以不是每个人都能运行你的测试。例如,并非所有版本的touch 都允许选项跟随位置参数——POSIX 标准仅在选项出现时才要求touch 工作。
  • @CharlesDuffy 我用我的真正问题更新了这个问题。我只是想弄清楚为什么会这样。你能帮帮我吗?
  • 啊!使用-mindepth 1 豁免目录本身。

标签: shell unix scripting find


【解决方案1】:

问题询问为什么find 的结果中有一个额外的.,即使不存在同名的文件或目录。答案很简单:. 始终 存在,即使它被隐藏。使用ls -a 显示隐藏的内容,您会看到它的存在。


您现有的 find 命令并不能免除目标目录本身 -- . -- 成为合法结果的原因,这就是为什么您得到的结果比您预期的要多。

添加以下过滤器:

-mindepth 1  # only include content **under** the file or directory specified

...或者,如果您只想计算 文件,请使用...

-type f      # only include regular files

假设 GNU find,顺便说一句,这一切都可以变得更加高效:

check_dir() {
  local d1 d2 # otherwise these variables leak into global scope
  d1=$2
  d2=$(gdate -d "+ 1 day $d1" '+%Y%m%d') # assuming GNU date is installed as gdate
  n=$(find "$1" -mindepth 1 \
                -name "*${d1}*" -o \
                '(' -newermt "$d1" '!' -newermt "$d2" ')' \
                -printf '\n' | wc -l)
  if (( n != $3 )); then
    echo "$1 = $n"
  fi
}

【讨论】:

  • 哦!我已经尝试过了,但不幸的是,我的发现不支持 newermt。 :(
  • 有一个原因,我把它作为我的答案的一个附录,而不是整个事情。
  • 顺便说一句,如果您不需要递归,是否有理由使用find 完全,而不是仅在 bash 中本地执行逻辑?
  • 是的,我需要在所有目录中检查文件名中包含特定日期或最近 1 天最后修改的文件。
  • 顺便说一句,我能再问你一件事吗?我正在做的 d2=$((d1 + 1)) 计算第二天的日期,但是对于像 20151231 这样的月末日期,这将不起作用。我如何添加该异常?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-02
  • 1970-01-01
  • 2023-03-03
  • 2019-01-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多