Reputation: 931
I'm trying to keep my function inspect_files to the principle of single responsibility, I know I could easily calculate the file count inside of that function and print it there, but is there a more elegant solution to count files than this?
(Note, I don't want a recursive file count.)
# Snippet:
dir_name="$HOME/$1"
inspect_files() {
local content
for content in "$dir_name"/*; do
printf "%s\n" "${content##*/}"
done
count_files "$dir_name"
}
count_files() {
local count
local dir="$1"
count=$(ls -1 "$dir_name" | wc -l)
printf "\nTotal: %d\n" "$count"
}
if is_found "$dir_name"; then
inspect_files
else
echo 'Not a directory.'
fi
Upvotes: 1
Views: 167
Reputation: 414
I think that a more elegant and performant solution to count files can be this one:
find "$dir_name" -mindepth 1 -maxdepth 1 -ignore_readdir_race -printf x | wc -m
So that your counting fuction would look like this:
count_files() {
local count
local dir="$1"
count=$(find "$dir_name" -mindepth 1 -maxdepth 1 -ignore_readdir_race -printf x | wc -m)
printf "\nTotal: %d\n" "$count"
}
This version works by printing an "x" for each item in the directory, then counting the characters with wc -m. It has a very low memory footprint, does no sorting and you can redirect output to a file to count asynchronously - for very large directories - (side-note: this counts also hidden files and subdirs, so you eventually have to filter them out with -and -not -name '.*'
).
Tip: -ignore_readdir_race
makes find
ignore errors due to deletion of files during the operation (maybe you don't want to stop operating on the files in the directory during the count).
There is plenty of questions about counting files with bash, so I imagined that it can be helpful to use a function (like you did) to simplify the operation. I'll copy your approach and put it in my .barshrc and .zshrc ;-)
Upvotes: 0
Reputation: 63902
The next function:
inspect_files() {
find "$1/" -type f -maxdepth 1 -print0 | grep -zc .
}
return the plain file count in a given direcotry, e,g:
tmpcount=$(inspect_files /tmp)
echo "File count in /tmp is: $tmpcount"
if you want count everything (not only plain files) use a simlper:
inspect_files() {
find "$1/" -maxdepth 1 -print0 | grep -zc .
}
The slash after "$1/"
ensure you counting in the directories what are symbolic links, like
$ ls -ld /tmp
lrwxr-xr-x@ 1 root wheel 11 27 jul 2012 /tmp -> private/tmp
Upvotes: 1
Reputation: 753665
What about:
list_and_count_files()
{
local content
local count
count=0
for content in "${1:-.}"/*; do
printf "%s\n" "${content##*/}"
((count++))
done
printf "\nTotal: %d\n" "$count"
}
This name is a more accurate description of what your original function does. Note that the directory to be analyzed is passed as an argument to the function, but defaults to .
(the current directory) if you don't pass anything. This decouples the function from the variable $dir_name
, which is much better for isolation.
Upvotes: 1