2016-03-19 5 views
1

Примечание редактора: Этот вопрос неоднозначный, потому что он смешивает два несвязанных задачи:
(а) в печати простых имен файлов (без компонентов пути) с помощью -printf действия, и
(б) проход простое имя файла в качестве аргумента в контексте -exec действия через {}
(а) ошибочно воспринимается как способ осуществлять (b).
Эта путаница привела, по крайней мере, к одному ответу, посвященному (а).
Linux Найти Command Скрыть базовый каталог

Я пытаюсь использовать команду find, чтобы перечислить все каталоги по определенному пути, но скрыть этот путь на выходе. -printf «% P \ п» флаг должен скрыть/путь/к/каталогу /, но это не работает:

find /path/to/directory/* -maxdepth 0 -type d -printf "%P\n" -exec sudo tar -zcpvf {}.tar.gz {} \; 

Например, вышеприведенная команда будет создавать архивы с:

/path/to/directory/dir1 
/path/to/directory/dir2 
/path/to/directory/dir3 

Как я могу изменить свою команду на выходе этого:

dir1 
dir2 
dir3 

Обратите внимание: я знаю, что могу сделать выше, кд/путь/к/директории/затем с помощью команды поиска, но очень важно, чтобы избежать используя cd и делать все это с помощью s ingle команда поиска.

+1

Если ответ решает вашу проблему, пожалуйста, примите его, нажав на большую галочку (✓) рядом с ней. Если вы нашли другие ответы полезными, попробуйте их проголосовать. Приём и голосование помогают будущим читателям. См. [Соответствующую статью справочного центра] (http://stackoverflow.com/help/someone-answers). Если ваш вопрос еще не полностью ответил, пожалуйста, сообщите об этом. – mklement0

+0

См. [Что делать, если кто-то отвечает на мой вопрос?] (Http://stackoverflow.com/help/someone-answers) – zdim

ответ

1
find /path/to/directory/* -maxdepth 0 -type d -exec basename {} \; 

найти все каталоги find /path/to/directory/* -maxdepth 0 -type d

-exec basename {} \; - выполнить basename команды с параметрами результата из поиска

+0

Хотя этот фрагмент кода может решить вопрос, [включая объяснение] (http: // meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода. – gunr2171

+0

Это предложение ничего не решит, так как оно полностью не учитывает флаг MY -exec. –

+0

Кажется, что это работает некоторое время, тогда «Can not stat: Нет такого файла или каталога». Может быть, xargs не работает со слишком большим количеством файлов? –

0

Поскольку вы только обработка ребенок каталогов (непосредственные подкаталоги), петли оболочки может быть более простое решение:

(cd "/path/to/dir" && for d in */; do sudo tar -zcpvf "${d%/}".tar.gz "$d"; done) 

Я знаю, что вы хотите избежать cd, но, включив всю команду в (…), она запускается в подклассу , поэтому рабочий каталог текущей оболочки. остается неизменной.

В оставшейся части этого ответа обсуждается, как решить проблему, используя GNU find.

Решение -execdir также будет работать с BSD/OSX find, и на самом деле было бы проще.


Что касается получения find «ы -printfтолько печати в имена файлов, без каких-либо компонентов каталога: используйте формат %f спецификатор:

find /path/to/dir/* -maxdepth 0 -type d -printf "%f\n" 

Это будет печатать простое имена всех непосредственных подкаталогов в указанной директории.

Однако , что вы печать не оказывает никакого влияния на то, что {} расширяется, когда с помощью -exec действия: {} всегда расширяется на пути в соответствие, которая неизменно включает в себя компонент пути, указанному в качестве входных данных.

Однако -execdir действие может дать вам то, что вы хотите:

  • он переходит в каталог под рукой перед выполнением указанной команды

  • расширяется {} к ./<filename> - т.е. простое имя файла (в данном случае имя каталога), префикс ./ - и передает его указанной команде.

Таким образом:

find /path/to/dir -mindepth 1 -maxdepth 1 -type d -execdir sudo tar -zcpvf {}.tar.gz {} \; 

Caveat: -execdir только ведет себя так, как описано для файлов, которые являются потомками из входных путей; для самих входных трактов, любопытно, {} все еще расширяется до входных путей as-is[1] .

Таким образом, команда выше делает не использовать подстановку (/path/to/dir/*) с -maxdepth 0, но вместо этого использует /path/to/dir и позволяет find сделать перечисление содержащихся элементов, которые, чем на уровне - следовательно -maxdepth 1; так как сам входной путь не должен быть включен, необходимо добавить -mindepth 1.

Обратите внимание, что поведение затем немного отличается: findвсегда включает скрытых элементов в перечислении, а оболочечная подстановка (*) по умолчанию делает не.


Если ./ префикс в {} разложения должны быть зачищены, требуется дополнительная работа:

find /path/to/dir -mindepth 1 -maxdepth 1 -type d \ 
    -execdir sh -c 'd=${1##*/}; sudo tar -zcpvf "$d".tar.gz "$d"' - {} \; 

Вовлечение оболочки (sh) позволяет отгонки префикс ./ используя расширение параметра оболочки (${1##*/} будет, по сути, полосой любой компонент пути). Обратите внимание на фиктивный аргумент -, который оболочка присваивает $0, что нас здесь не интересует; {} затем становится параметром оболочки $1.


[1] С ./ префиксом, если входной путь сам по себе относительно; обратите внимание, что BSD/OSX find не проявляет эту причуду: он всегда расширяет {} до . mene filename, без любой компонент пути.

+0

Это ПОЧТИ работает! Кроме того, он ставит перед собой уродливый пустой каталог, например: ./dir/filename.txt. Есть ли способ удалить ./, поэтому выход будет только dir/filename.txt? –

+0

Да, tar работает правильно, но вместо dir1 dir2 в моем архиве я получаю ./dir1 ./dir2. –

+0

@GTSJoe: см. Мое обновление. – mklement0