Jak sprawić, by chown działał rekurencyjnie?

285

Mam katalog o nazwie, pdfsktóry zawiera kilka podkatalogów i podkatalogów. Chcę zmienić własność wszystkich plików PDF we wszystkich podfolderach. Właśnie próbowałem tego:

chown -R someuser:somegroup *.pdf

... ale nie zmieniło to własności plików PDF w podkatalogach. Użytkownik i grupa istnieją.

Według strony podręcznika dla chown, -Rpowinno to oznaczać rekurencyjne:

-R, --recursive
          operate on files and directories recursively

czego mi brakuje?

Nathan Long
źródło

Odpowiedzi:

291

Tryb rekurencyjny działa tylko na katalogach, a nie na plikach. Używając glob '* .pdf', powłoka przekazuje listę plików do chown, która widzi, że są to pliki i zmienia uprawnienia do plików, które widzi, i to wszystko.

Pamiętaj, że w powłokach glob jest oceniany przez powłokę, a nie przez polecenie. Jeśli glob pasuje do plików, są one przekazywane do polecenia i polecenie nigdy nie wie, że glob istnieje. (Różni się to od tego, w jaki sposób wiersz poleceń systemu Windows służył do wykonywania różnych czynności). Jeśli masz katalog, z treścią coś takiego:

machine:$ ls -F
file1.pdf  file2.pdf  other.txt  subdir/

I wpisałeś:

chown -R someuser:somegroup *.pdf

Najpierw powłoka utworzy listę: plik1.pdf plik2.pdf

a następnie uruchom polecenie:

chown -R someuser:somegroup file1.pdf file2.pdf

Widzisz, nie ma katalogu dla -R do działania. Robi to, o co go prosiłeś - zmienia prawa własności do dwóch plików w wierszu poleceń, ignorując tę ​​dziwaczną flagę -R.

Aby zrobić, co chcesz, użyj „* .pdf” jako wzorca dla tego katalogu i podkatalogów, możesz użyć find, który może znaleźć pliki, które pasują do wzorca nazwy pliku (lub wielu innych kryteriów) i przekazać do podkomendy

find . -type f -name '*.pdf' | xargs chown someuser:somegroup

To zaczyna się w aktualnym reż. aby wyszukać pliki (typ pliku f) wzorzec nazwy, '*.pdf'a następnie przechodzi do xargs, który konstruuje linię poleceń do chmod. Zwróć uwagę na cytaty wokół wzorca '*.pdf', pamiętaj, że powłoka utworzy glob, jeśli to możliwe, ale chcesz przekazać wzór find, więc musisz go zacytować.

Ponieważ w nazwach plików mogą znajdować się spacje, należy zastosować sztuczkę, aby zapewnić bezpieczeństwo nazw plików ze spacjami:

find . -type f -name '*.pdf' -print0 | xargs -0 chown someuser:somegroup

W bash 3 i niższych jest to sposób, w jaki musisz to zrobić. Bardziej zaawansowane globowanie jest dostępne w bash 4 (with shopt -s globstar) i innych powłokach. To samo w przypadku Zsh przy użyciu rekurencyjnego globu **:

chown -R someuser:somegroup ./**/*.pdf
Rich Homolka
źródło
1
Edytowane w celu odzwierciedlenia tego bash 4 z shopt -s globstarrekursywnym globowaniem.
kojiro
@kojiro dzięki! jak widać, nadal używam bash3
Rich Homolka
2
Na stronie podręcznika pokazanej na oryginalnym plakacie znalazłem, że Chown -R rzeczywiście zmienił właściciela folderów ORAZ plików. Nie ma potrzeby szukania. Używanie mennicy 15.
gwideman,
@gwideman Wiem, że to stare ... Ale tak, oczywiście -R rekurencyjne. OP miał problem z bardzo specyficznym typem rekurencji, z rozszerzeniem i filtrowaniem „typ pliku to plik”
Rich Homolka
@RichHomolka Ah. OP powiedział, że pliki znajdują się w katalogu o nazwie „pdfs”, więc założyłem, że problem polega na tym, jak określić pdf jako katalog do ponownego wykorzystania, i że wszystkie zawarte pliki to pdfs, więc nie trzeba ich specjalnie zaznaczać. Ale możesz mieć rację, jeśli zadaniem jest wybranie tylko plików pdf i pozostawienie innych bez zmian.
gwideman
52
chown -R someuser:somegroup /your/folder/here/*

Spowoduje to zastosowanie chown do wszystkich plików i wszystkich podkatalogów i podkatalogów określonego folderu. Używaj ostrożnie.

Sprachprofi
źródło
2
Jakoś sudo chown -R user ./dla mnie działało, ale sudo chown -R user ./*nie
Slav
1
Wiem, że to jest stare, ale chociaż odpowiada to na nagłówek, nie odpowiada na pytanie. Jest to w rzeczywistości nieco gorsze niż to, co OP już próbował.
Rich Homolka
2
@RichHomolka Przywieziono mnie tutaj tylko ze względu na tytuł pytania, cieszę się, że znalazłem tę odpowiedź.
Félix Gagnon-Grenier
@ FélixGagnon-Grenier wystarczy. Jeśli ta odpowiedź Ci odpowiada, jestem bardzo szczęśliwy. Ale to nie zadziałałoby w przypadku pierwotnego pytania.
Rich Homolka
Wydaje się, że to nie działa w przypadku plików kropek, takich jak .env.
Ryan
14

Możesz użyć findnarzędzia:

find . -name '*.pdf' -exec chown someuser:somegroup {} +

Proszę nie zapomnieć o cytatach *.pdf. W przeciwnym razie powłoka spróbuje ją rozwinąć. Oznacza to, że już powłoka zastąpi *.pdfnazwy wszystkich plików PDF znalezionych w bieżącym katalogu. Ale nie tego chcesz. Chcesz znaleźć pliki PDF znajdujące się w podkatalogach. Przy okazji: to też jest problem z twoją chownkomendą.

bmk
źródło
1
Musiałem znaleźć +zgrabną sztuczkę pod kątem wydajności. -exec command {} +Ten wariant akcji -exec uruchamia określone polecenie na wybranych plikach, ale linia poleceń jest budowana przez dołączenie każdej wybranej nazwy pliku na końcu; całkowita liczba wywołań polecenia będzie znacznie mniejsza niż liczba dopasowanych plików. Wiersz poleceń jest budowany w taki sam sposób, jak xargswiersze poleceń. {}W poleceniu dozwolona jest tylko jedna instancja Polecenie jest wykonywane w katalogu startowym.
Patrick M
@PatrickM jedna (niewielka) inna przewaga nad + vs; .... plus nie jest meta postacią powłoki i nie trzeba jej uciekać
Rich Homolka
6

Komenda

chown -R someuser:somegroup *.pdf

będzie ponownie wyświetlać katalogi tylko wtedy, gdy nazwa katalogu kończy się na .pdf. Potrzebujesz czegoś takiego:

find . -name "*.pdf" -exec chown someuser:somegroup {} \;
Mike Scott
źródło
Technicznie spadnie tylko o jeden poziom. czy nazywasz to prawdziwą rekurencją, czy nie jest ćwiczeniem dla użytkownika :)
Rich Homolka
1

aby zmienić własność katalogu rekurencyjnie, po prostu użyj:

sudo chown -R <username>:<groupname> <dir name>

tutaj nazwa użytkownika = nowy użytkownik, który powinien być właścicielem katalogu

nazwa grupy = nowa grupa, która powinna być właścicielem katalogu

każdy plik / katalog ma właściciela użytkownika i właściciela grupy

KawaiKx
źródło
Nie robi to, o co poprosił PO. To zmienia własność wszystkiego, OP poprosił o określony zestaw plików.
Rich Homolka
0

Używam treezamiast tego:

 sudo tree -fai ~/.blabla  | xargs -L1 -I{} sudo chown youruser:youruser {}

Uważaj również, aby nie uruchamiać rekurencyjnego chown lub chmod w katalogu „/” lub innym katalogu systemowym.

Eduard Florinescu
źródło
0

Aby stać się właścicielem wszystkich plików w katalogu, użyj

find directory -type f -name '*' | sudo xargs -d '\n' chown $USER

zamiast

sudo chown $USER directory\*

lub

sudo chown --recursive $USER directory

co może nie działać, jeśli * jest zbyt wiele argumentów (zbyt wiele plików w katalogu) lub które nie robią tego, co chcesz.

masterxilo
źródło