Как я могу заставить чоун работать рекурсивно?

285

У меня есть каталог, pdfsкоторый содержит кучу подкаталогов и подкаталогов. Я хочу изменить владельца всех файлов PDF во всех подпапках. Я только что попробовал это:

chown -R someuser:somegroup *.pdf

... но это не изменило владение PDF-файлами в подкаталогах. Пользователь и группа существуют.

Согласно справочной странице для chown, значение -Rдолжно быть рекурсивным:

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

Что мне не хватает?

Натан Лонг
источник

Ответы:

292

Рекурсивный режим работает только с каталогами, а не с файлами. С помощью глобуса '* .pdf' оболочка передает список файлов chown, который видит эти файлы, и изменяет права доступа к файлам, которые он видит, и все.

Помните, что в оболочках глобб оценивается оболочкой, а не командой. Если глобус соответствует файлам, они передаются команде, и команда никогда не узнает, что глобус существует. (Это отличается от того, как командная строка Windows использовала что-то). Если у вас есть каталог, с содержимым что-то вроде:

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

И вы набрали:

chown -R someuser:somegroup *.pdf

Оболочка должна была сначала составить список: file1.pdf file2.pdf

и затем запустите вашу команду:

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

Видите, нет каталога для действия -R. Он делает то, что вы просили - изменить владельца двух файлов в командной строке, игнорируя этот странный флаг -R.

Чтобы сделать то, что вы хотите, использовать «* .pdf» в качестве шаблона для этого каталога и подкаталогов, вы можете использовать find, который может найти файлы, которые соответствуют шаблону имени файла (или много других criterea) и передать подкоманде

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

Это начинается в текущем каталоге '.' для поиска файлов (тип файла f) шаблона имени '*.pdf'затем передается xargs, который создает командную строку для chmod. Обратите внимание на кавычки вокруг шаблона '*.pdf', помните, что оболочка создаст глобус, если сможет, но вы хотите, чтобы шаблон был передан find, поэтому вам нужно заключить его в кавычки.

Поскольку в именах файлов могут быть пробелы, вы хотите использовать трюк, чтобы сделать его безопасным:

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

В bash 3 и ниже вам нужно это сделать. Более мощные шатания доступны в bash 4 (с shopt -s globstar) и других оболочках. То же самое в zsh, используя рекурсивный глоб **:

chown -R someuser:somegroup ./**/*.pdf
Рич Гомолка
источник
1
Отредактировано, чтобы отразить, что bash 4 with shopt -s globstarделает рекурсивное сглаживание.
Кодзиро
@kojiro спасибо! как вы можете сказать, я все еще использую bash3
Rich Homolka
2
На man-странице, показанной оригинальным постером, я обнаружил, что chown -R действительно менял владельца папок и файлов. Не нужно искать. Использование Mint 15.
gwideman
@ всем, я знаю, что это старый ... Но да, конечно -R делает рекурсивный. У OP только что была проблема с очень специфическим типом рекурсии, расширением и фильтрованным «тип файла - файл»
Rich Homolka
@RichHomolka Ах. OP сказал, что файлы находятся в каталоге с именем «pdfs», поэтому я предположил, что проблема заключалась в том, как указать pdfs в качестве каталога для рекурсии, и что все содержащиеся в нем файлы были pdfs, поэтому нет необходимости специально выбирать их. Но вы вполне можете быть правы, если задача состоит в том, чтобы выбирать только файлы PDF и оставлять другие без изменений.
gwideman
52
chown -R someuser:somegroup /your/folder/here/*

Это применимо к chown для всех файлов и всех подкаталогов и подкаталогов указанной папки. Используйте с осторожностью.

Sprachprofi
источник
2
Как-то sudo chown -R user ./сработало для меня, но sudo chown -R user ./*не сработало
славянин
1
Я знаю, что это старо, но хотя это отвечает заголовку, не отвечает на вопрос. Это на самом деле немного хуже, чем то, что ОП уже пробовал.
Богатая Гомолка
2
@RichHomolka Приведенный сюда только из-за названия вопроса, я очень рад найти этот ответ.
Феликс Ганьон-Гренье
@ FélixGagnon-Grenier достаточно справедливо. Если этот ответ работает для вас, я очень рад. Но это не сработало бы для первоначального вопроса.
Rich Homolka
Кажется, это не работает для точечных файлов, таких как .env.
Райан
14

Вы можете использовать findутилиту:

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

Пожалуйста, не забывайте цитаты вокруг *.pdf. В противном случае оболочка попытается его расширить. Это означает, что уже оболочка заменит *.pdfимена всех файлов PDF, найденных в текущем каталоге. Но это не то, что вы хотите. Вы хотите найти файлы PDF, расположенные в подкаталогах. Кстати: это тоже проблема с вашей chownкомандой.

БМК
источник
1
Я должен был найти +, аккуратный трюк для производительности. -exec command {} +Этот вариант действия -exec запускает указанную команду для выбранных файлов, но командная строка создается путем добавления каждого выбранного имени файла в конце; общее количество вызовов команды будет намного меньше, чем количество совпавших файлов. Командная строка строится почти так же, как и xargsее командные строки. Только один экземпляр {}допускается в команде. Команда выполняется в начальном каталоге.
Патрик М
@PatrickM одно (незначительное) другое преимущество перед + против; .... плюс не является метасимволом оболочки и не должен быть экранирован
Rich Homolka
6

Команда

chown -R someuser:somegroup *.pdf

будет возвращать каталоги только в том случае, если имя каталога заканчивается на .pdf. Вам нужно что-то вроде:

find . -name "*.pdf" -exec chown someuser:somegroup {} \;
Майк Скотт
источник
Технически это пойдет только на один уровень вниз. называете ли вы настоящую рекурсию или нет, это упражнение для пользователя :)
Rich Homolka
1

для рекурсивного изменения владельца каталога просто используйте:

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

здесь username = новый пользователь, который должен быть владельцем каталога

groupname = новая группа, которая должна быть владельцем каталога

каждый файл / каталог имеет владельца пользователя и владельца группы

KawaiKx
источник
Это не делает то, что спросил ОП. Это меняет владение всем, OP запросил определенный набор файлов.
Богатая
0

Я использую treeвместо этого:

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

Также постарайтесь не запускать рекурсивные команды chown или chmod в каталоге '/' или другом системном каталоге.

Эдуард Флоринеску
источник
0

Чтобы стать владельцем всех файлов в каталоге, используйте

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

вместо

sudo chown $USER directory\*

или же

sudo chown --recursive $USER directory

это может не сработать, если * (слишком много файлов в каталоге) выдано слишком много аргументов, или если не получается то, что вы хотите соответственно.

masterxilo
источник