Policz całkowitą liczbę plików w określonym katalogu z określonym rozszerzeniem

32

Chcę policzyć całkowitą liczbę plików w danym katalogu, które kończą się rozszerzeniem „.mp4”.

Otrzymuję następujące polecenie:

ls -F |grep -v / | wc -l

Liczy wszystkie pliki w danym katalogu, ale chcę liczbę plików, które kończą się rozszerzeniem .mp4.

Czy jest na to jakieś polecenie Ubuntu?

Prakash V Holkar
źródło
2
Prosta, poprawna i bezpośrednia odpowiedź to @ louis-matthijssen. ls -1obsługa znaków nowego wiersza sprawia, że ​​w tym przypadku warto przeanalizować lsdane wyjściowe. Zaznaczony jest niepoprawny w przypadku użycia opcji -R.
Rmano

Odpowiedzi:

19

Tutaj możesz to zrobić w ten sposób

ls -lR /path/to/dir/*.jpg | wc -l

To daje ci liczyć

sk1712
źródło
5
Dlaczego -R? Po co robić pełne, statgdy potrzebujesz tylko nazwy pliku? Dlaczego nie ls -1 *.jpg| wc -l? (ok, nie działa, jeśli masz nazwy plików z nowymi
liniami
2
... a pytanie brzmiało „zliczanie liczby plików w katalogu”. Ponadto wyświetli rekurencyjnie całą zawartość podkatalogów, których nazwa kończy się na .jpg , a nie pliki w podkatalogach kończące się na .jpg. Czy kiedykolwiek to przetestowałeś?
Rmano
1
Pytanie brzmi „pliki w określonym katalogu”, co oznacza, że ​​rekursja podkatalogu nie jest pożądana.
David Richerby
1
To również kończy się niepowodzeniem, jeśli w katalogu znajduje się zbyt wiele plików (ponieważ *.jpgjest on rozszerzany przez powłokę, a nie przez ls) i jeśli istnieją pliki, których nazwy zaczynają się od łączników.
David Richerby
2
@DavidRicherby Pomija nazwy zaczynające się od .. Ale tak naprawdę działa dobrze z myślnikami w nazwach, z wyjątkiem sytuacji, gdy /path/to/dirpusty ciąg lub ścieżka względna zaczyna się od łącznika. Ale myliłem się wcześniej , mówiąc, że lszastępuje postacie ?. Dzieje się tak, gdy stdout jest terminalem, ale tutaj wyjście jest potokiem, więc lswysyła wszystkie znaki z nazw plików do wc. To sprawia, że ​​ta odpowiedź jest błędna bez flagi -qlub, -baby zmienić to zachowanie , ponieważ nazwy plików mogą zawierać znaki nowej linii. Odpowiedź l0b0 jest wolna od tych problemów.
Eliah Kagan 10.10.17
42

Niestety ten łagodny problem jest trudny do rozwiązania w sposób, który obsługuje wszystkie nazwy plików i jest przenośny. Jest to bezpieczne (obsługuje ukryte pliki, ścieżki zawierające spacje, myślniki, a nawet znaki nowej linii) i jest zgodne z POSIX :

find /path/to/directory -mindepth 1 -type f -name "*.mp4" -printf x | wc -c

Jeśli nie chcesz, aby była rekurencyjna, po prostu dodaj -maxdepth 1.

Nie powinieneś analizować lsdanych wyjściowych.

Test:

$ cd -- "$(mktemp -d)"
$ touch -- -foo.mp4 .bar.mp4 .bat.mp4 'baz.mp4
> ban.mp4'
$ find . -mindepth 1 -type f -name "*.mp4" -exec printf x \; | wc -c
4

Porównaj z zaakceptowaną odpowiedzią :

$ ls -lR ./*.mp4 | wc -l
3

Lub inne sugestie:

$ find . -name "*.mp4" | wc -l
5
$ ls -1 *.mp4 | wc -l
ls: invalid option -- '.'
Try 'ls --help' for more information.
0
$ find . -name "*.mp4" | wc -c # Answer fixed at a later time
51
$ find . -name "*.mp4" | wc -l
5
$ find . | grep -i ".mp4$" | wc -l
5
$ ls . | grep ".mp4$" | wc -l
3
10b0
źródło
2
Chociaż ta odpowiedź jest poprawna i niezawodna, możesz jej użyć -printf xzamiast -exec printf x \;. Innymi słowy: find /path/to/directory -mindepth 1 -type f -name "*.mp4" -printf x | wc -c nie ma potrzeby -execwykonywania printfpolecenia zewnętrznego , które w przypadku dużej liczby plików będzie działało bardzo wolno , ponieważ findmusi rozwidlić (2) kopię samej siebie, a następnie wykonać (2) /usr/bin/printf . Z -exec printf x \;, należy to zrobić raz dla każdego pliku .
Eliah Kagan,
-printfnie jest obsługiwany w POSIXfind , dlatego go nie użyłem.
l0b0 11.10.17
1
Ani nie są, -mindepthi -maxdepthktórych użyłeś.
Eliah Kagan,
Dobra uwaga, nie podniosłem tego!
l0b0,
BSD findzawiera -mindepthi -maxdepthnie zawiera, -printfwięc doceniam włączenie obu.
Joseph
11

Ten wyszukuje, sortuje i wyświetla wszystkie pliki według rozszerzenia w kolejności:

find . -type f | sed 's/.*\.//' | sort | uniq -c
zgnieciony
źródło
Doskonały! Chciałbym tylko dodać | sort -rnna końcu i być może -mindepth 1aktualny reż.
Pablo A
A może fajka, head -naby uzyskać górną n.
Raman,
taka świetna odpowiedź, wielkie dzięki
Dennis Golomazov
5

Myślę, że to bardzo proste, jak wykonać następujące polecenia.

$ find . -name "*.mp4" | wc -l
8

lub

$ find . | grep -i ".mp4$" | wc -l
8

Myślę, że powyższe polecenia obliczają liczbę nazw plików i katalogów *.mp4

więc sugeruję użycie -type fopcji jako findparametru jak poniżej.

$ find . -name "*.mp4" -type f | wc -l
8

Ponadto ls -lRmoże być używany jakofind .

xiaodongjie
źródło
2

Możesz użyć ls -1 *.mp4 | wc -l.

Spowoduje to wyświetlenie listy wszystkich plików kończących się .mp4, drukowanie każdego pliku w nowej linii ( ls -1 *.mp4), potokowanie danych wyjściowych, do wcktórych policzy liczbę nowych linii za pomocą -lflagi.

Louis Matthijssen
źródło
Nie jestem pewien, dlaczego zostało to odrzucone, to działa
Panther
Ponieważ *.mp4jest rozszerzany przez powłokę, nie ls, to się nie powiedzie, jeśli .mp4w katalogu znajduje się tak wiele plików, że ich lista nie może zostać przekazana lsjako argument.
David Richerby
@Rmana Przetestuj w katalogu zawierającym plik o nazwie--.mp4
David Richerby
@DavidRicherby tak, masz rację. --rozwiąże drugi przypadek; ten pierwszy wyświetli komunikat o błędzie (potrzebujesz dużo plików!) i kolejne fajne pytanie tutaj. Narożniki, ale warto zauważyć, tak.
Rmano
1
@Rmano bez dodawania -qczy -bto ma nie tolerują newlines w nazwach plików. Jeśli uciekasz ls -1 *.mp4ze swojego terminalu bez rury, zobaczysz , lsże jego stdout jest terminalem i bierze, -qjak sugeruje, drukowanie ?s. Ale to zachowanie zanika, gdy wyjście jest przesyłane potokowo. ls -1 *.mp4 | wc -lprzeliczyć, jeśli są nowe linie. ls -1 *.mp4 | catpokazuje, co wc„widzi”. (Podobnie -1sugerowane jest, gdy standardowe wyjście nie jest terminalem, więc jest opcjonalne.) ls -1q -- *.mp4 | wc -lPrawie działa, ale nie z zerowymi plikami .mp4.
Eliah Kagan,
0

To powinno dać ci listę plików z rozszerzeniem .mp4

ls /path/to/directory | grep ".mp4$"

W połączeniu z wc -ldaje liczyć

ls /path/to/directory | grep ".mp4$" | wc -l

jeśli chcesz, aby wyszukiwanie zawierało podkatalogi

ls -lR /path/to/directory | grep ".mp4$" | wc -l
Ukośnik wsteczny
źródło
się nie liczy
Panther
dał mi go, gdy użyłemwc -l
Back.Slash
użyj ls bez pipingu, aby grep i skrócić swoją odpowiedź. Został opublikowany co najmniej dwa razy.
Panther
@ bodhi.zazen ls /directory/*.mp4powoduje, że powłoka rozszerza glob i wykonuje coś takiego. ls /directory/file1.mp4 /directory/file2.mp4 ...To się nie powiedzie, jeśli katalog zawiera więcej plików mp4, niż można przekazać jako argumenty ls.
David Richerby
@DavidRicherby - to nie jest moja komenda ls, używam find;)
Panther
0

W skrócie, jednym zimnym rozwiązaniem jest używanie tablic z glob:

$ files=( *.mp4  )
$ echo ${#files[@]}
30
Sergiy Kolodyazhnyy
źródło
0
ls | grep --count \.csv$

Zamień (.csv na żądane rozszerzenie)

Objaśnienie: Myślę, że prostym schematem jest pobranie listy plików i policzenie rozszerzenia za pomocą grep. \.dopasować .i $dopasować rozszerzenie na końcu linii. Działa, ponieważ gdy dane wyjściowe ls są przesyłane potokowo, w jednej linii wysyłana jest jedna nazwa pliku, którą można zweryfikować, uruchamiając:

ls | cat
Mohsin Raza
źródło
1
Zauważ, że zamiast grep --countmożesz również użyć grep -c.
Mohsin Raza