Скопируйте файл несколько раз с именами, которые получены из списка

(У меня нет под рукой машины Solaris, поэтому я работаю с manpages, так что, возможно, вам придется немного поиграть с синтаксисом)

Вы можете использовать тот факт, что любой пустой каталог будет иметь количество ссылок, равное 2 (только само имя каталога, dir, плюс его собственный dir/. , ссылаются на него); в UNIX запрещено (жестко) ссылаться на каталог, кроме как в процессе добавления его к (одной) записи каталога или добавления записей каталога к нему, так что это инвариант. (В основном1.)

Solaris не поддерживает опцию -empty, но он поддерживает опцию -links для поиска вещей с точно n ссылками. Таким образом, команда, которая вам нужна (я думаю; см. ниже), следующая:

find /home/.../Desktop -type d -links 2 -print

кстати...

Ваше использование слова "рекурсивно" немного двусмысленно, поэтому обратите внимание, что это не найдет каталоги, не содержащие ничего, кроме пустых каталогов (или так далее, рекурсивно). Если вы хотите этого, вопрос очень прост, если вы хотите определить их, чтобы удалить. Просто повторно выполните команду выше, добавив -exec rmdir {} \; пока не останется ни одного; при каждом запуске вы будете удалять родительские деревья на один уровень глубже, так что это не займет много запусков, если только у вас нет очень глубокого дерева каталогов, состоящего из одних пустых каталогов. (В зависимости от того, как работает find(1) в Solaris, я думаю, вы также можете выполнить find . -type d -exec rmdir -p {}; только один раз (опция -p сообщает rmdir(1), что он может удалять каталоги, содержащие пустые каталоги), но поскольку затем он будет пытаться пройти по удаленным каталогам, вы получите кучу сообщений об ошибках, которые можно игнорировать, вперемешку с теми, которые могут вас волновать, поэтому я бы сделал это итеративным способом. )

(Обратите внимание, что опция -depth в find(1) здесь не поможет, поскольку файлы stat()'d слишком рано, чтобы счетчик ссылок успел обновиться. В противном случае можно выполнить find -depth $dir -type d -links 2 -exec rmdir {} \; и одного запуска было бы достаточно.)

Если вы хотите определить и "внутренне пустые" каталоги, и каталоги, не содержащие ничего, кроме пустых каталогов (или так далее, рекурсивно), не удаляя их, это сложнее. Я предполагаю, что одна командная строка возможна, но это будет зверь (я уверен, что кто-то другой попробует это сделать позже), по крайней мере, без использования perl или сумасшедших sed/awk заклинаний.

Но что бы я сделал, так это скопировал дерево каталогов куда-нибудь, скажем /tmp/tree-copy, затем выполнил команду

find /tmp/tree-copy -type d -links 2 -print -exec rmdir {} \; | tee -a /tmp/empty-dirlist

несколько раз, пока не прекратится вывод. (Команда tee -a позволяет увидеть вывод, но также добавляет его в файл /tmp/empty-dirlist).

Затем вы захотите удалить /tmp/tree-copy или что-то еще из каждой строки файла;

perl -i -lpe 's{^/tmp/tree-copy/}{}' /tmp/empty-dirlist

подойдет для этого, или вы можете использовать ваш текстовый редактор. Вуаля! , список пустых каталогов, где "пустой" определяется как "не содержащий ничего, кроме каталогов". (Вы также можете поместить perl, или sed, или что угодно, в конвейер перед tee -a, если хотите. )


  1. Прежде чем какой-нибудь остряк укажет на это, это не обязательно верно для файловой системы точки монтирования; менеджеры файловой системы в некоторых ОС могут свободно использовать количество ссылок точки монтирования в своих личных целях, поэтому вы часто будете видеть каталоги точки монтирования, пустые или нет, с количеством ссылок 1 (незаконно для каталогов в других обстоятельствах), 2, или что-то еще значимое, но не связанное с фактическим количеством ссылок. Поэтому, если вы собираетесь сделать вышеописанное, вам следует убедиться, что вы потенциально не пересекаете точки монтирования, поскольку возможно, хотя и маловероятно, что одна из них будет иметь количество ссылок, равное 2.
0
10.10.2018, 17:50
2 ответа

Почему ты убегаешь от H и W?

\Hи \Wимеют особое значение и отличаются от Hи W.

echo "         WHERE     x=10" |sed 's/ *WHERE \+/WHERE /g'
3
28.01.2020, 02:16

Просто поставьте \перед словами.

echo "         WHERE     x=10" |sed 's/ *WHERE \+/WHERE /g'
WHERE x=10

\в регулярных выражениях используется в качестве escape-символа для различных типов совпадений.

\wиспользуется для поиска символа слова, то есть символа из a-z, A-Z, 0-9, включая символ подчеркивания_().

Поскольку версия в верхнем регистре отрицает совпадение, ваш \Wозначает, что не соответствует ни одному символу, что, очевидно, приводит к сбою регулярного выражения для ваша входная строка.

Попробуйте например:

echo "         {HERE     x=10" |sed 's/ *\WHERE \+/WHERE /g'
WHERE x=10

это работает, потому что{совпадает с с \W(, поскольку {НЕ является символом слова )!

2
28.01.2020, 02:16

Теги

Похожие вопросы