shell脚本获取一个目录、及其子目录下的所有文件

#!/bin/sh
read -p "input path:" FilePath;
function getAllFiles()
{
        fileList=`ls $FilePath`;
        for fileName in $fileList;
        do
           #if test -f $fileName; then
           if [-f $fileName ];then
              echo $fileName;
           elif test -d $fileName; then
              cd $fileName;
              FilePath=`pwd`;
              getAllFiles;
              cd ..;
           else
              echo "$FilePath is a invalid path";
           fi
        done
}
cd $FilePath;
getAllFiles;
echo "DONE";

<think>好的,我现在需要帮用户解决如何用Shell脚本统计指定目录及其子目录下所有.txt文件的总行数的问题。首先,我得回忆一下Shell脚本中处理文件统计的常用方法。用户之前的问题是关于统计一级子目录文件的数量,现在他要的是所有子目录中的.txt文件的总行数,所以需要更深入的处理。 首先,我需要确定如何递归查找所有.txt文件。find命令应该可以做到,比如使用`find目录 -name "*.txt"`来获取所有.txt文件的路径。然后,对每个文件进行行数统计,通常用wc -l命令。不过,直接使用wc-l处理多个文件的话,它会输出每个文件的行数以及总行数。但用户需要的是所有文件的总和,所以可能需要把每个文件的行数提取出来再累加。接下来,考虑如何将这两个命令结合起来。可以用一个循环遍历所有找到的.txt文件,然后对每个文件使用wc -l,再将结果累加。或者,是否可以用更高效的方式,比如使用xargs将文件列表传递给wc -l,然后处理输出结果?例如,`find .-name"*.txt"| xargs wc -l`,这会输出每个文件的行数和最后的总行数。但用户可能只需要总行数,这时候可以grep 'total'来提取总数,不过需要注意wc-l在某些情况下可能不会显示total,特别是当文件数量较少时,或者不同系统上的行为可能不同。因此,这种方法可能不够可靠。另一种方法是逐个处理每个文件的行数,然后累加到变量中。这样虽然可能效率稍低,但更可靠。比如,使用一个循环,对每个文件执行wc-l,然后截取行数部分,累加到sum变量里。例如: sum=0forfile in$(find$dir-name"*.txt");dolines=$(wc-l< "$file")sum=$((sum +lines))doneecho "总行数:$sum" 不过,这里需要注意文件名中的空格问题,因为使用for循环默认是按空格分隔的,如果文件名有空格,会导致错误。为了避免这个问题,应该使用find的-exec选项或者使用while循环配合read命令来处理。更安全的做法是: find"$dir"-name"*.txt"-print0 |while IFS=read -r -d ''file;dolines=$(wc-l< "$file")sum=$((sum +lines))done不过,在Bash中,管道中的while循环是在子shell中执行的,sum的累加不会传递到父shell,所以这种方法会导致sum始终为0。因此,需要避免使用管道,而是使用进程替换或者将结果保存到临时变量中。可能的解决方案是使用临时文件或者使用进程替换,或者直接在循环外部初始化sum变量,并在循环内部更新。比如: sum=0whileIFS= read-r-d'' file; dolines=$(wc -l <"$file")sum=$((sum+ lines)) done< <(find"$dir" -name "*.txt" -print0) echo"总行数: $sum"这里使用了进程替换和find的-print0来处理带有空格的文件名,确保安全。这样,sum变量就能在循环结束后保持累加的结果。 另外,用户可能需要指定目录作为脚本的参数,或者硬编码在脚本中。比如,允许用户输入目录参数,或者默认当前目录。需要处理参数是否存在的情况,给出错误提示。 还需要考虑如果目录不存在,或者没有.txt文件的情况,脚本应该如何处理。比如,添加错误检查,或者输出友好的提示信息。 总结步骤:1.使用find命令递归查找所有.txt文件,处理带有空格的文件名。2.逐个读取每个文件,统计行数。3.累加所有行数。4.输出总行数。可能的优化点:-使用xargs结合wc -l,但需要处理total行的提取问题。 -使用AWK来处理wc的输出,直接求和。例如,使用以下命令:find "$dir"-name"*.txt"-execwc-l{} +| awk'END{print$1}'这里,-exec wc -l {}+会将所有文件传递给wc-l,wc会输出每个文件的行数和总行数(如果有多个文件的话)。然后,AWK的END模式会处理最后一行,如果是多个文件,最后一行是总行数,但如果是单个文件,则只有一行。因此,这种方法可能不可靠,因为当文件数量较少时,wc不会输出总行数。例如,当只有一个文件时,总行数就是该文件的行数,而当有多个文件时,最后一行是总行数。所以,正确的做法应该是用AWK来累加所有行数,不管是否有总行数。 改进的AWK命令:find "$dir"-name"*.txt"-execwc-l{} +| awk'{sum +=$1} END{printsum}' 这样,不管wc输出的是每个文件的行数还是总行数,AWK都会累加每一行的第一个字段,即每个文件的行数,最后输出总和。这种方法更可靠,且效率较高,因为减少了循环的开销。因此,最终的脚本可能更简洁,使用find结合exec和awk来处理,这样既高效又安全,还能处理文件名中的特殊字符。所以,脚本可以写成:#!/bin/bash#检查参数是否存在if[ $# -ne1]; thenecho "用法:$0<目录>"exit1fitarget_dir="$1"#检查目录是否存在if [! -d "$target_dir" ];thenecho"错误:目录不存在 $target_dir"exit1fi#统计所有.txt文件的总行数total_lines=$(find"$target_dir"-typef -name "*.txt" -exec wc -l {}+ |awk '{sum +=$1} END{printsum}') echo"总行数: $total_lines" 这样,用户只需要传递目录作为参数,脚本会检查参数和目录是否存在,然后使用find查找所有.txt文件,统计行数,并用awk累加得到总和。这种方法避免了循环和子shell的问题,处理效率更高,也更安全。 不过,需要注意,某些系统上的wc -l可能会在文件名中包含空格时输出错误,但使用-exec参数直接传递给wc -l,每个文件单独处理,可能不会有问题。或者,结合find的-print0和xargs-0来处理:total_lines=$(find "$target_dir" -type f-name"*.txt"-print0 |xargs-0wc-l| awk'{sum+= $1}END {print sum}')但两种方法效果类似,可能根据系统不同有所差异,但总体来说都是可行的。最后,测试脚本,确保它能正确处理各种情况,包括空文件、多个子目录中的文件文件名包含空格等。</think>要编写Shell脚本统计指定目录及其子目录下所有`.txt`文件的总行数,可以结合`find`命令与行数统计工具`wc`,并通过管道进行数据汇总。以下是具体实现步骤和脚本示例: --- ### 实现方法 1. **递归查找文件**:使用`find`命令搜索目标目录下所有`.txt`文件,并通过`-type f`确保只统计文件。 2. **统计行数**:将文件列表传递给`wc -l`计算每个文件的行数。 3. **累加结果**:通过`awk`汇总所有文件的行数。 ```bash #!/bin/bash #################################### # 功能:统计指定目录及其子目录下所有.txt文件的总行数 # 使用:./script.sh <目标目录> #################################### # 检查参数是否存在 if [ $# -ne 1 ]; then echo "用法: $0 <目录>" exit 1 fi target_dir="$1" # 检查目录是否存在 if [ ! -d "$target_dir" ]; then echo "错误: 目录不存在 $target_dir" exit 1 fi # 统计总行数 total_lines=$(find "$target_dir" -type f -name "*.txt" -exec wc -l {} + | awk '{sum += $1} END {print sum}') # 输出结果 echo "总行数: $total_lines" ``` --- ### 关键点解析 1. **递归查找文件**:`find "$target_dir" -type f -name "*.txt"`会递归搜索所有`.txt`文件[^1]。 2. **行数统计与汇总**: - `-exec wc -l {} +`:对每个文件执行`wc -l`统计行数。 - `awk '{sum += $1} END {print sum}'`:累加所有文件的行数并输出总和[^2]。 3. **安全性**:`-exec`参数直接处理文件路径,避免文件名含空格导致的错误。 --- ### 示例输出 ```bash $ ./count_lines.sh ~/documents 总行数: 12345 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值