5

我必须在 Bash 中找到恰好包含 16 行的文件。

我的想法是:

find -type f | grep '/^...$/'

有谁知道如何利用find+grepfind+ awk

然后,

  • 将匹配的文件移到另一个目录。
  • 删除所有不匹配的文件。
4

7 回答 7

7

我会这样做:

wc -l **/* 2>/dev/null | awk '$1=="16"'
于 2013-06-17T12:35:40.870 回答
5

把事情简单化:

find . -type f |
while IFS= read -r file
do
    size=$(wc -l < "$file")
    if (( size == 16 ))
    then
        mv -- "$file" /wherever/you/like
    else
        rm -f -- "$file"
    fi
done

如果您的文件名可以包含换行符,那么谷歌查找和读取选项来处理它。

于 2013-06-17T12:40:16.977 回答
2

您应该使用grep而不是wc因为wc计算换行符\n并且如果最后一行不以换行符结尾则不计算在内。

例如

grep -cH '' * 2>/dev/null | awk -F: '$2==16'

对于更正确的方法(没有错误消息,并且没有参数列表太长的错误),您应该将其与findandxargs命令结合使用,例如

find . -type f -print0 | xargs -0 grep -cH '' | awk -F: '$2==16'

如果您不想计算空行(因此只有包含至少一个字符的行),您可以将 替换'''.'. 而不是 awk,您可以使用第二个 grep,例如:

find . -type f -print0 | xargs -0 grep -cH '.' | grep ':16$'

这将找到包含 16 个非空行的所有文件......等等......

于 2013-06-17T20:05:23.640 回答
1

GNU sed

sed -E '/^.{16}$/!d' file
于 2013-06-17T12:42:16.753 回答
0

这个片段将完成工作:

find . -type f -readable -exec bash -c \
    'if(( $(grep -m 17 -c "" "$0")==16 )); then echo "file $0 has 16 lines"; else echo "file $0 doesn'"'"'t have 16 lines"; fi' {} \;

因此,如果您需要删除不是 16 行长的文件,并将那些长 16 行的文件移动到 folder /my/folder,这将是:

find . -type f -readable -exec bash -c \
    'if(( $(grep -m 17 -c "" "$0")==16 )); then mv -nv "$0" /my/folder; else rm -v "$0"; fi' {} \;

请注意引用,"$0"以便对任何带有有趣符号(空格,...)的文件名都是安全的。

我正在使用该-v选项rm并且mv很冗长(我想知道发生了什么)。-n选项mv是 no-clobber:不覆盖现有文件的安全性;如果您有旧系统,则此选项可能不可用。

这种方法的好处。对于任何包含有趣符号的文件名,它都是非常安全的。

坏事。它为找到的每个文件分叉一个bash和一个grep和一个mvrm。这可能很慢。这可以使用更棘手的东西来解决(同时对于文件名中的有趣符号仍然保持安全)。如果你真的需要,我可以给你一个可能的答案。如果文件不能(重新)移动,它也会中断。

评论。我正在使用-readableto 选项find,因此它只考虑可读的文件。如果您有此选项,请使用它,您将拥有更强大的命令!

于 2013-06-18T09:17:46.167 回答
0

我会去

find . -type f | while read f ; do
  [[ "${f##*/}" =~ ^.{16}$ ]] && mv "${f}" <any_directory>  || rm -f "${f}"
done

或者

find . -type f | while read f ; do
  [[ $(echo -n "${f##*/}" | wc -c) -eq 16 ]] && mv "${f}" <any_directory>  || rm -f "${f}"
done

替换<any_directory>为您实际要将文件移动到的目录。

顺便说一句, find 命令将进入子目录。如果您不想要这个,那么您应该更改 find 命令以满足您的需要。

于 2013-06-18T01:13:20.947 回答
0

版本:

#!/usr/bin/bash

for f in *; do # Look for files in the present dir
  [ ! -f "$f" ] && continue # Skip not simple files
  cnt=0
  # Count the first 17 lines
  while ((cnt<17)) && read x; do ((++cnt)); done<"$f"
  if [ $cnt == 16 ] ; then echo "Move '$f'"
  else echo "Delete '$f'"
  fi
done
于 2013-06-17T12:49:12.157 回答