Найти файлы и распечатать только их родительские каталоги - PullRequest
15 голосов
/ 07 марта 2012

У меня есть следующие команды. Везде, где присутствует файл .user.log, нам нужно распечатать родительские каталоги (т.е. hht и wee1.). Как это можно сделать?

$ cd /nfs//office/ && find . -name '.user.log'
./hht/info/.user.log
./wee1/info/.user.log

Ответы [ 7 ]

15 голосов
/ 07 марта 2012

Я что-то здесь упускаю.Конечно, все эти регулярные выражения и / или циклы не являются необходимыми, однострочник сделает работу.Кроме того, решения for for foo in $ () не будут работать, если в именах путей есть пробелы.

Просто дважды используйте dirname с xargs, чтобы получить родительский родитель ...

# make test case
mkdir -p /nfs/office/hht/info
mkdir -p /nfs/office/wee1/info
touch /nfs/office/hht/info/.user.log
touch /nfs/office/wee1/info/.user.log

# parent's parent approach
cd /nfs//office/ && find . -name '.user.log' | xargs -I{} dirname {} | xargs -I{} dirname {}

# alternative, have find print parent directory, so dirname only needed once...
cd /nfs//office/ && find . -name ".user.log" -printf "%h\n"  | xargs -I{} dirname {}

Производит

./hht
./wee1
4 голосов
/ 10 августа 2016

Вы можете легко это сделать с помощью опций форматирования действия -printf, равного find (см. man find).

cd /nfs//office/ && find . -name '.user.log' -printf "%h\n"
./hht/info
./wee1/info

со страницы руководства :

Screenshot of find manpage

%h\n напечатает путь для каждого файла в новой строке.

Обратите внимание, что -printf только для GNU. Это не будет работать на macOS (система BSD).

3 голосов
/ 07 марта 2012
for file in $(find /nfs/office -name .user.log -print)
do
    parent=$(dirname $(dirname $file))
    echo $parent
done

РЕДАКТИРОВАТЬ: Извините, пропустил, что вы хотите каталог дедушки.

1 голос
/ 07 марта 2012

@ trojanfoe имеет правильную идею; this - это просто способ заставить его работать безопасно с любым именем файла и практически любой командой в цикле:

while IFS= read -r -d '' -u 9
do
    echo "$(dirname -- "$(dirname -- "$REPLY")")"
done 9< <( find "/nfs/office/" -name '.user.log' -print0 )

Если вы хотите, чтобыэхо только уникальные имена:

while IFS= read -r -d '' -u 9
do
    echo "$(dirname -- "$(dirname -- "$REPLY")")"
done 9< <( find "/nfs/office/" -name '.user.log' -print0 ) | sort -u
0 голосов
/ 18 ноября 2017
find -type f -exec bash -c 'echo "${1%/*}"' bash {} \;
0 голосов
/ 07 марта 2012

Вы можете сделать что-то вроде этого:

cd /nfs/office/ && find . -name '.user.log' | xargs -n1 -I{} expr match {} '\(\.\(\/[^/]*\/\)\?\)'

, где xargs использует expr match для извлечения части, которая начинается с . до первого совпадения каталога между символами косой черты (/dir/).

Альтернативная версия с использованием sed будет выглядеть следующим образом:

cd /nfs/office/ &&  find . -name 'file.txt' | sed -r 's|(\./([^/]*/)?).*|\1|'
0 голосов
/ 07 марта 2012
find /nfs/office -name '.user.log' | while read line
do
    echo $line | awk -F/ '{print $(NF-1),$NF}'
done
...