Подтвердить что ты не робот

Скопируйте файлы и каталоги с помощью оболочки 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
4b9b3361

Ответ 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

Для подсчета каталогов