2

Я пытаюсь заставить GNU находить исключенные записи ДО указанного имени файла.

Возьмите этот пример дерева:

./foo
./foo/another.txt
./foo/bar
./foo/bar/world
./foo/bar/world/test.txt
./foo/bar/world/hello.txt

(Там будет куча других файлов в world и другие каталоги , а также, поэтому я не просто искал hello.txt

Я хочу сопоставить все, кроме «test.txt» и его родительских каталогов.

Выходные данные должны быть просто foo/bar/world/hello.txt .

Эта команда дает правильные результаты, но она довольно грязная и выдаст неправильные результаты, если будет несколько каталогов с одинаковыми именами:

find * ! -name test.txt -a ! -name foo -a ! -name bar -a ! -name world

2 ответа2

1

Скажите, find вас интересуют только файлы, а не каталоги.

find ./foo -type f ! -name test.txt

Обновить:

Предположим, у нас есть немного более сложный пример:

$ find ./foo
./foo
./foo/baz
./foo/baz/b.csv
./foo/baz/a.txt
./foo/bar
./foo/bar/c.txt
./foo/bar/world
./foo/bar/world/hello.txt
./foo/bar/world/test.txt

Если ваша цель - удалить что-либо, вам нужно указать -depth чтобы файлы были видны перед их каталогами:

$ find ./foo -depth
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo

Если вы знаете путь, который хотите сохранить, мы можем разработать регулярное выражение, которое соответствует его частям:

$ find ./foo -depth -regextype posix-extended -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo

Тогда мы можем просто отменить регулярное выражение, чтобы получить материал, который вы хотите удалить:

$ find ./foo -depth -regextype posix-extended ! -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt
0

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

find . -mindepth $depth ! -name test.txt

С вашей структурой каталогов я получаю:

$ find . -mindepth 4 ! -name test.txt
./foo/bar/world/hello.txt

Что именно то, что вы ожидаете.


РЕДАКТИРОВАТЬ: это должно быть лучше (но уродливее!). Он находит каталог, в котором находится test.txt и находит все файлы в нем. Преимущество заключается в том, что он полностью независим от родительских путей, он будет автоматически их вычислять.

EXCLUDEFNAME="test.txt"; find $(find . -name "$EXCLUDEFNAME" -exec dirname {} \; -quit) -mindepth 1 ! -name "$EXCLUDEFNAME"

Многолинейность лучше:

EXCLUDEFNAME="test.txt"
targetpath="$(find . -name "$EXCLUDEFNAME" -exec dirname {} \;)"
find "$targetpath" -mindepth 1 ! -name "$EXCLUDEFNAME"

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .