Скопируйте файлы и каталоги с помощью оболочки script
Я изучаю скрипты bash и написал script для подсчета файлов и каталогов в каталоге, который поставляется в качестве аргумента. Я работаю так, что мне кажется странным, и мне интересно, есть ли более простой способ сделать это.
Я прокомментировал код, который будет работать, но оставил его в качестве сравнения. Я пытаюсь заставить for
-loop работать, вместо этого используя if
в нем, чтобы определить, является ли элемент в заданном местоположении файлом или каталогом.
Изменить. Я только узнал, что прокомментированный код также подсчитывает все файлы и каталоги в подкаталогах данного местоположения! Есть ли способ предотвратить это и просто подсчитать файлы и каталоги данного местоположения?
#!/bin/bash
LOCATION=$1
FILECOUNT=0
DIRCOUNT=0
if [ "$#" -lt "1" ]
then
echo "Usage: ./test2.sh <directory>"
exit 0
fi
#DIRS=$(find $LOCATION -type d)
#FILES=$(find $LOCATION -type f)
#for d in $DIRS
#do
# DIRCOUNT=$[$DIRCOUNT+1]
#done
#for f in $FILES
#do
# FILECOUNT=$[$FILECOUNT+1]
#done
for item in $LOCATION
do
if [ -f "$item" ]
then
FILECOUNT=$[$FILECOUNT+1]
elif [ -d "$item" ]
then
DIRCOUNT=$[$DIRCOUNT+1]
fi
done
echo "File count: " $FILECOUNT
echo "Directory count: " $DIRCOUNT
По какой-то причине вывод for
-loop, независимо от того, где я указываю местоположение, всегда возвращает:
File count: 0 , Directory count: 1
Ответы
Ответ 1
Вы не итерируете по списку файлов внутри данного каталога; добавьте /*
после $LOCATION
. Ваш script должен выглядеть так:
...
for item in $LOCATION/*
do
...
Как указано dogbane, просто добавление /*
будет считать только файлы, которые не начинаются с .
; для этого вы должны сделать следующее:
...
for item in $LOCATION/* $LOCATION/.*
do
...
Ответ 2
Используйте find
, как показано ниже. Это решение будет считать имена файлов с пробелами, символами новой строки и точками.
FILECOUNT="$(find . -type f -maxdepth 1 -printf x | wc -c)"
DIRCOUNT="$(find . -type d -maxdepth 1 -printf x | wc -c)"
Обратите внимание, что DIRCOUNT
включает текущий каталог (.
). Если вы этого не хотите, вычтите 1.
((DIRCOUNT--)) # to exclude the current directory
Ответ 3
Чтобы решить проблему, которую вы можете использовать:
FILECOUNT=$(find $LOCATION -type f | wc -l)
DIRCOUNT=$(find $LOCATION -type d | wc -l)
find
будет искать все файлы (-type f
) или каталоги (-type d
) рекурсивно в $LOCATION
; wc -l
будет подсчитывать количество строк, записанных в stdout в каждом случае.
Однако, если вы хотите узнать, bash script может быть лучшим способом. Некоторые комментарии:
- Если вы хотите искать только файлы/каталоги только в
$LOCATION
(не рекурсивно под их подкаталогами и т.д.), вы можете использовать for item in $LOCATION/*
, где *
будет расширяться до списка файлов/каталогов в $LOCATION
. Отсутствует *
, поэтому ваш оригинальный script возвращает 0/1 (потому что сам каталог $LOCATION
является единственным подсчитанным элементом).
- Сначала вы можете проверить, что
$LOCATION
на самом деле является каталогом с [ -d $LOCATION ]
.
- Для арифметических выражений используйте
$(( ... ))
, например FILECOUNT=$(( FILECOUNT + 1 ))
.
- Если вы хотите найти все файлы/каталоги рекурсивно, вы можете комбинировать
find
с циклом.
Пример:
find $LOCATION | while read item; do
# use $item here...
done
Ответ 4
... am wondering if there is a simpler way of doing it.
Если вы так говорите;)
В качестве альтернативы уменьшите script до
find /path/to/directory | wc -l
Для текущего каталога выполните:
find . | wc -l
Ответ 5
Используйте
find $LOCATION -maxdepth 1 -type f | wc -l
Для подсчета файлов и
find $LOCATION -maxdepth 1 -type d | wc -l
Для подсчета каталогов