对于备份程序的一致性检查,我想定义一个函数来计算目录中的所有文件,包括子目录、子子目录等中的所有文件。
到目前为止我正在尝试的解决方案如下:
countfiles() {
local cdir=$1
local files=$(ls -la $cdir | grep -cv '^[dl]')
local dirstring=$(ls -la $cdir | grep '^d' | egrep -o ' \.?[^[:space:].][^[:space:]]+$')
local directories=(${dirstring//"\n"/})
echo ${directories[@]}
for dir in ${directories[@]}; do
echo -n "$dir "
echo -n 'filecount >> '
local dirfiles=$(countfiles "$cdir/$dir")
echo -n $dirfiles
echo ' <<'
#files=$(($files+$dirfiles))
done
echo $files
}
这给了我以下输出:
.config .i3 .scripts
.config filecount >> gtk-3.0 termite gtk-3.0 filecount >> 2 << termite filecount >> 2 << 1 <<
.i3 filecount >> 5 <<
.scripts filecount >> 2 <<
5
虽然我的计数器的实现$files
是在 atm 上注释的,并且我可能需要将其取消本地化,但现在我将所有变量设置为本地变量以避免任何干扰。
目录树如下:
/.scripts/backup_dotfiles.sh
/.config/termite/config
/.config/gtk-3.0/settings.ini
/.i3/config
/.i3/i3blocks.conf
/.i3/lockicon.png
/.i3/lockscreen.sh
/.gtkrc-2.0
/.bashrc
/.zshrc
/.i3
/.Xresources
我的问题:
- 为什么除了主目录之外的文件总是+1?
- 为什么它会计算“.config”目录中的任何内容,因为那里没有文件?
- 我怎样才能解决这个问题?
答案1
您可能只想使用find
.假设您的文件名称中没有换行符,只需执行以下操作:
find "$dir" -type f | wc -l
-type f
匹配常规文件,但不匹配目录、管道、套接字等。
通常的输出find
用换行符分隔文件名,因此如果任何名称包含换行符,输出将不明确。使用 GNU find,类似这样的事情可以工作:
find "$dir" -type f -printf . | wc -c
它只find
为每个文件打印一个点,并计算点的数量。
其他版本find
没有,-printf
但我们可以使用用双斜杠传递输入路径的技巧。它们被视为单个斜杠,但不会自然地出现在输出中,因为文件名不能包含斜杠。然后计算输出中的双斜杠数量:
find "$dir//" -type -f | grep -c //
如果我们想纯粹使用 shell 脚本来做到这一点,我们可以让 shell 列出文件名,无需使用ls
,例如在 Bash 中:
#!/bin/bash
files=0
shopt -s dotglob
countfiles() {
local f;
for f in * ; do
if [ -f "$f" ] ; then # count regular files
files=$((files + 1))
elif [ -d "$f" ] ; then # recurse into directories
cd "$f"
countfiles
cd ..
fi
done
}
cd "$1"
countfiles
echo $files
答案2
您可以使用以下命令获取目录和子目录中的文件数:
find path_to_directory -type f | wc -l
答案3
为什么除了主目录之外的文件总是+1?
因为 ls -la 还将字符串添加total 20
到输出中。我可以看到,对于“master”目录,它还显示+1 值。
为什么它会计算“.config”目录中的任何内容,因为那里没有文件?
同样的原因。total ..
产生的字符串ls
。
我怎样才能解决这个问题?
不要使用你的脚本:)我的意思是,它真的太复杂了。我们find
这里过得很好。您的所有脚本都会变成类似的内容(如果您需要每个目录的文件):
find $yourdir -type d | while read dir ; do
echo "$dir == $(find $dir -maxdepth 1 -type f | wc -l) files" ;
done
或者只是(如果您需要总和值):
find $yourdir -type f | wc -l