在UNIX

时间:2016-02-10 16:33:31

标签: bash unix grep directory

我试图遍历目录中的所有文件,其名称作为命令行参数(例如myfolder)给出。对于每个文件,grep命令应该在文件夹上运行,并计算在文本文件中找到短语(例如myphrase)的次数。

当我运行我的代码时,类似于下面,我得到错误"没有这样的文件或目录"。我尝试使用./myscript.sh myfolder./myscript.sh /[fullpath]/myfolder调用脚本,但它们都会导致相同的错误。

for f in "$1"
do
  echo "processing $f file"
  grep -o '<myphrase>' "$f" | wc -l
done

关于出了什么问题的任何想法? 如果它有助于从与文本文件相同的文件夹中运行脚本,并且必须使用文件夹名称作为参数调用该命令 - 我必须遵循这两个烦人的要求。

编辑:为此文件夹运行ls -ld会显示drwxr-xr-x@ 829 user staff 28186 7 Feb 17:19 my folder

4 个答案:

答案 0 :(得分:2)

如上所述anubhava

在你的for循环使用中:

for f in "$1"/*
do
...
done

然后,您可以检查f是否是包含以下内容的文件:

[[ -f $f ]]

在循环中执行必要的逻辑:

[[ -f $f ]] && grep -o '<myphrase>' "$f" | wc -l

总结如下:

for f in "$1"/*
do
 echo "processing $f file"
 [[ -f $f ]] && grep -o '<myphrase>' "$f" | wc -l
done

答案 1 :(得分:0)

您需要为目标目录添加通配符匹配。
比较foo.sh中的两个for循环(“原始”被注释掉)。

此外,我将grep命令修改为只是一个回声,所以你有一个
简单的方法来预览将要尝试执行的内容。

来自foo.sh的样本输出

编辑:我添加了-r(下面,在foo.sh中)来检查dir $ 1的读取权限。这很难成功;当我针对一个无读取目录进行测试时,它只是看起来像目录中没有任何内容(即使它有* .java和* .class文件,如上所示)。

更清楚的是,针对不可读的dir运行看起来像这样(这是没有-r检查):

$ chmod a-r tmp
$ ./foo.sh tmp
$1="tmp"
processing tmp/* file
grep -o '<myphrase>' "tmp/*" | wc -l
$ 

注意上面的“处理tmp / *文件”行。 for循环将文字字符“tmp / *”输入$ f变量。
哪个很好,如果模式与任何东西都不匹配,那正是万能扩展应该如何工作。
但是我们没有检查来自grep的错误代码,所以可能很难
注意grep抱怨“文件tmp / *未找到”

foo.sh输出(修订版)

$ chmod a+r tmp
$ ./foo.sh
$1=""
Error: no directory specified.
$ ./foo.sh foo.sh
$1="foo.sh"
Error: "foo.sh" is not a dir.
$ ./foo.sh tmp
$1="tmp"
processing tmp/Foo.class file
grep -o '<myphrase>' "tmp/Foo.class" | wc -l
processing tmp/Foo.java file
grep -o '<myphrase>' "tmp/Foo.java" | wc -l
$ chmod a-r tmp
$ ./foo.sh tmp
$1="tmp"
Error: no read permissions on dir "tmp".
$ 

foo.sh

#!/bin/bash

echo "\$1=\"$1\""
if [ -z "$1" ]; then
   echo "Error: no directory specified."
   exit 1
fi
if [ ! -e "$1" ]; then
   echo "Error: dir \"$1\" does not exist."
   exit 1
fi
if [ ! -d "$1" ]; then
   echo "Error: \"$1\" is not a dir."
   exit 1
fi
if [ ! -r "$1" ]; then
   echo "Error: no read permissions on dir \"$1\"."
   exit 1
fi
# maybe default to "." if $1 is empty ?
# original: for f in "$1"
for f in "$1"/*
do
  echo "processing $f file"
  echo "grep -o '<myphrase>' \"$f\" | wc -l"
  # maybe  change myphrase to $2 ?
done

另外,正如其他地方所指出的,您正在编写自己的“find”命令版本。另一种可能性是......

那么怎么样?

我添加这个只是为了鼓励你在某些点查看find命令。

免责声明:编写自己的脚本完全正常。 研究和理解如何推销你自己是有价值的。

发现确实很复杂,但从长远来看,非常值得攀登发现的学习曲线。

请注意,以下99%只是评论。

ezfind.sh(示例)

#!/bin/bash

# example ussage:
# ezfind.sh "$HOME/my_dir"  "foo.*bar"
#  "$1" is the start point, any directory path (relative or absolute).
#  -type f limits matches to regular files (e.g. probably dont
#  want to run grep dirs or devices).
#  exec args ar funky, see below.
#  Optional: see bottom of this script for notes about -depth
#  to limit how deep find will search.
#------------------------------------------------------
find "$1" -type f -exec grep -i -o   "$2" '{}' ';'
#                       \________/  \___/ \__/ \_/
#                           |        |     |   |
#   command ----------------+        |     |   |
#   pattern for grep ----------------+     |   |
#   find replaces {} w/filename------------+   |
#   find exepects a semicolon for end-of-cmd---+

# Quoting is funky for -exec arguments.
# The values have to to survive current bash interpretation,
# so they can be passed to find's argument list.
# Then find turns around and passes them to grep's argument list.
# The semicolon is normally a bash statement separator so we
# need to quote it (or escape it) so it gets passed to find
# as part of the arg list.

# find -exec will replace {} with current filename.
# find gives you a crazy amount of file name, file type and date range options.
#    search for all file names in /what/ever matching "*.txt"
#    search for all file names matching "*.sh" modified in the last hour.
# for more on find, see here:
# http://www.softpanorama.org/Tools/Find/using_exec_option_and_xargs_in_find.shtml
# 
# What if I don't want to search every sub-folder, all the way down?
# Also about not traversing subdirectories, consider the -depth modifer.
# To just search the target directory, modify the above to read:
#     find "$1" -maxdepth 0  ....
# To just search the target directory and immediate subdirectories...
#     find "$1" -maxdepth 1  ....
# For a nice summary of -depth, see here:
#     http://www.tech-recipes.com/rx/31/limit-the-depth-of-search-using-find/

答案 2 :(得分:0)

从目录详细信息中,似乎目录名称中有一个空格:

  

drwxr-xr-x @ 829用户工作人员28186 7月17日17:19我的文件夹

尝试运行如下脚本或从目录名称中删除空格:)

  

./ myscript.sh"我的文件夹&#34;

答案 3 :(得分:-1)

你可以这样做:

find <directory> -type f -exec egrep -c '<regular expression>' {} +

请注意,由于find找不到不存在的文件,因此无需检查文件是否存在。另请注意,find遍历找到的子目录(-maxdepth 1的可调行为)。

E.g:

find /usr/include -type f -exec egrep -c 'int128' {} +