计算找到的每个文件的行数

时间:2014-08-12 23:55:11

标签: bash unix

我认为我不太清楚Unix中的find命令是如何工作的;我有这个代码来计算每个文件夹中的文件数,但我想计算找到的每个文件的行数,并将总数保存在变量中。

find "$d_path" -type d -maxdepth 1 -name R -print0 | while IFS= read -r -d '' file; do 


     nb_fichier_R="$(find "$file" -type f -maxdepth 1 -iname '*.R' | wc -l)" 

     nb_ligne_fichier_R= "$(find "$file" -type f -maxdepth 1 -iname '*.R' -exec wc -l {} +)"
     echo "$nb_ligne_fichier_R"

done

输出:

  43 .//system d exploi/r-repos/gbm/R/basehaz.gbm.R  
  90 .//system d exploi/r-repos/gbm/R/calibrate.plot.R
  45 .//system d exploi/r-repos/gbm/R/checks.R
 178 total: File name too long

我可以保存到变量中的总行数吗?这里在我的例子中只保存178和我文件夹中的每个文件" $ d_path"

非常感谢

4 个答案:

答案 0 :(得分:0)

解决方案:

find "$d_path" -type d -maxdepth 1 -name R | while IFS= read -r file; do


     nb_fichier_R="$(find "$file" -type f -maxdepth 1 -iname '*.R' | wc -l)"
     echo "$nb_fichier_R" #here is fine

    find "$file" -type f -maxdepth 1 -iname '*.R' | while IFS= read -r fille; do
        wc -l $fille #here is the problem nothing shown
    done
done

说明:

添加-print0第一个查找没有产生新行,因此您必须告诉read -d ''告诉它不要查找换行符。您的后续查找输出换行符,以便您可以使用不带分隔符的读取。我从所有来电中删除了-print0-d '',因此它是一致且惯用的。 unix世界的新行很好。

答案 1 :(得分:0)

对于命令:

find "$d_path" -type d -maxdepth 1 -name R -print0

最多可以有一个匹配的目录("$d_path/R")。对于那个目录,您要打印:

  1. *.R
  2. 匹配的文件数
  3. 对于每个此类文件,其中的行数。
  4. 我发现,使用辅助shell脚本最容易处理$d_path和文件名中的空格。辅助脚本处理在其命令行上命名的目录。然后,您可以从主find命令调用该脚本。

    counter.sh

    shopt -s nullglob;
    for dir in "$@"
    do
        count=0
        for file in "$dir"/*.R; do ((count++)); done
        echo "$count"
        wc -l "$dir"/*.R </dev/null
    done
    

    shopt -s nullglob选项意味着如果没有.R个文件(名称不以.开头),则glob扩展为空,而不是扩展为最后包含*.R的字符串。这个脚本很方便。 wc上的I / O重定向确保如果没有文件,它会从/dev/null读取,报告0行(而不是等待您输入内容)。

    另一方面,find命令将查找以.开头的名称以及不以 for file in "$dir"/*.R "$dir"/.*.R; do ((count++)); done 开头的名称,而通用符号则不会。最简单的方法是使用两个整体:

    find

    或使用 find . -type f -name '*.R' -exec sh -c 'echo $#' arg0 {} + (相当谨慎):

    find "$d_path" -type d -maxdepth 1 -name R -exec sh ./counter.sh {} +
    

    使用counter.sh

    -maxdepth 1

    此脚本允许多个子目录(如果删除counter.sh)的可能性,并调用sh ./counter.sh并将所有要检查的目录作为参数。脚本本身会仔细处理文件名,以便名称中是否有空格,制表符或换行符(或任何其他字符),它将正常工作。 find命令的counter.sh部分假定$PATH脚本位于当前目录中。如果可以在sh上找到,则可以删除./find

    讨论

    使用-print0执行带有文件名参数列表的命令的技术非常强大。它避免了xargs -0和使用$IFS的问题,但为您提供了对任意文件名的可靠处理,包括带有空格,制表符和换行符的名称。如果还没有一个命令可以执行您需要的操作(但您可以将其编写为shell脚本),那么请执行此操作并使用它。如果您可能需要多次执行此任务,则可以保留脚本。如果您确定不会,则可以在完成后将其删除。处理具有尴尬名称的文件通常比处理{{1}}更容易。

答案 2 :(得分:0)

考虑这个解决方案:

# If `"$dir"/*.R` doesn't match anything, yield nothing instead of giving the pattern.
shopt -s nullglob

# Allows matching both `*.r` and `*.R` in one expression. Using them separately would
# give double results.
shopt -s nocaseglob

while IFS= read -ru 4 -d '' dir; do 
    files=("$dir"/*.R)

    echo "${#files[@]}"

    for file in "${files[@]}"; do
        wc -l "$file"
    done

    # Use process substitution to prevent going to a subshell. This may not be
    # necessary for now but it could be useful to future modifications.
    # Let's also use a custom fd to keep troubles isolated.
    # It works with `-u 4`.
done 4< <(exec find "$d_path" -type d -maxdepth 1 -name R -print0)

另一种形式是使用readarray一次分配所有找到的目录。唯一需要注意的是它只能读取正常的换行终止路径。

shopt -s nullglob
shopt -s nocaseglob

readarray -t dirs < <(exec find "$d_path" -type d -maxdepth 1 -name R)

for dir in "${dirs[@]}"; do
    files=("$dir"/*.R)

    echo "${#files[@]}"

    for file in "${files[@]}"; do
        wc -l "$file"
    done
done

答案 3 :(得分:0)

也许我错过了一些东西,但这不是你想要的吗?

wc -l R/*.[Rr]