Список всех уникальных каталогов, которые содержат строку1, которые содержат файлы, которые содержат строку2 - PullRequest
0 голосов
/ 26 апреля 2018

Скажем, я хочу найти все каталоги, которые содержат определенную строку (скажем, a здесь), которые также содержат файлы, которые содержат определенную другую строку (скажем, это .txt файлы). Каковы разные способы сделать это? Одним из способов является подстановка команд, например:

mkdir dira; mkdir dirb
touch dira/file1.txt; touch dira/file2.doc; touch dirb/file3.doc
find `find . -type d -iname '*a'` -type f -iname '*.doc'

Однако это не работает, если я пытаюсь найти скрытые каталоги, содержащие этот файл:

find `find . -type d -iname '.*'` -type f -iname '*.doc'

В этом случае он просто печатает для вывода внутренней находки. Как это сделать? Чем больше способов сделать это, тем поучительнее. Сценарий оболочки также будет поучительным.

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

Чтобы предотвратить оценку действительного каталога (как ./ или ../pwd/), просто используйте:

find .* -mindepth 1 -maxdepth 1 -type f -iname '*.doc'
.dira/file11.doc
.dira/file10.doc
.dira/file9.doc
.dirb/file11.doc
.dirb/file10.doc
.dirb/file9.doc

После использования

touch .dir{a..b}/file{9..11}.doc

с более длинным шаблоном .dir * это проще:

find .dir* -type f -iname '*.doc'
.dira/file11.doc
.dira/file10.doc
.dira/file9.doc
.dirb/file11.doc
.dirb/file10.doc
.dirb/file9.doc

Подстановка команд тоже работает (не используйте устаревшие метки, пожалуйста)

find $(find . -mindepth 1 -type d -iname ".*") -type f -iname '*.doc'
./.dirb/file11.doc
./.dirb/file10.doc
./.dirb/file9.doc
./.dira/file11.doc
./.dira/file10.doc
./.dira/file9.doc
0 голосов
/ 26 апреля 2018

Это работает для меня:

#!/bin/bash

# Setup test directories
mkdir dira dirb .dirc .dird .hiddena

# Setup test files
touch dira/filea1.doc dira/filea2.doc dira/filea3.txt
touch dirb/fileb1.doc dirb/fileb2.doc dirb/fileb3.txt
touch .dirc/filec1.doc .dirc/filec2.doc .dirc/filec3.txt
touch .dird/filed1.doc .dird/filed2.doc .dird/filed3.txt
touch .hiddena/filehiddena1.doc .hiddena/filehiddena2.doc .hiddena/filehiddena3.txt

find . -type d -name "*a" -print | while read DIR 
do
    find $DIR -type f -name "*a*.doc" -print
done

Выход:

$ ./t.bash 
./dira/filea1.doc
./dira/filea2.doc
./.hiddena/filehiddena2.doc
./.hiddena/filehiddena1.doc

В моей первой версии использовался цикл for, но это может вызвать проблемы, если в именах каталогов есть пробелы, поэтому цикл while read.


Из вашего комментария я сделал это:

# Setup test directories
mkdir dira dirb .dirc .dird .hiddena

# Setup test files
touch dira/filea1.doc dira/filea2.doc dira/filea3.txt
touch dirb/fileb1.doc dirb/fileb2.doc dirb/fileb3.txt
touch .dirc/filec1.doc .dirc/filec2.doc .dirc/filec3.txt
touch .dird/filed1.doc .dird/filed2.doc .dird/filed3.txt
touch .hiddena/filehiddena1.doc .hiddena/filehiddena2.doc .hiddena/filehiddena3.txt
touch .hiddena/z

find . -type d -name "*a" -print | while read DIR 
do
    #find $DIR -type f -name "*a*.doc" -print
    find $DIR -type f -name z -print
done

Вывод, который я получаю:

$ ./t.bash 
./.hiddena/z

Так что я не понимаю, почему вы получаете двойной z.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...