Найдите файлы длиной имени файла

Обычная реализация изменения пароля включает hardlinking /etc/shadow кому: /etc/stmp (или некоторое аналогичное имя; link() будучи атомарным в локальных файловых системах, это составляет своего рода механизм файла блокировки), выписывая новый во временный файл, затем переименовывая оригинал /etc/shadow кому: /etc/shadow- или подобный и переименовывающий временный файл к /etc/shadow. Это сделано для устойчивости: в любом случае оригинал shadow файл, неизмененный, все еще существует и может быть восстановлен легко, даже если сбои питания в только неправильное время или что-то одинаково плохо (если он не уничтожает весь диск).

10
09.05.2016, 16:56
9 ответов

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

echo ?.go

(Между прочим, это - оболочка, которая оценивает шарик, не echo команда.)

Если Вы хотите посмотреть в каталогах рекурсивно, начиная с текущего каталога, инструмент для использования find:

find . -name '?.go'

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

3
27.01.2020, 20:01
  • 1
    Это также найдет каталоги, которые также соответствуют шаблону'? .go'. –  slm♦ 01.10.2013, 07:36
  • 2
    @slm, каталоги являются одним из многих типов файлов, OP не указывал, какими файлами он был после. –  Stéphane Chazelas 16.08.2015, 00:05

В первую очередь, grep перерывает содержание файлов, это не будет искать имена файлов. Для этого Вы хотите find. Это не имеет опции установить длину имени файла, но можно проанализировать, это производится для получения то, что Вы хотите. Вот некоторые примеры, которые я выполняю в каталоге, содержащем следующие файлы:

$ tree
.
├── a
├── ab
├── abc
├── abcd
└── dir
    ├── a
    ├── ab
    ├── abc
    └── abcd

Поиск файлов в этом каталоге возвраты:

$ find . -type f | sort
./a
./ab
./abc
./abcd
./dir/a
./dir/ab
./dir/abc
./dir/abcd

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

 $ find . -type f | grep -P '/.{3}$'

sed команда просто удаляет ./. -P флаг активирует Perl Совместимые Регулярные выражения, которые необходимы для {n} который является вещью PCRE и $ означает, "соответствуют концу строки".

Вы могли также просто сделать это:

find . -type f | grep -P '/...$'

Это хорошо для небольших чисел, вводящих 15 точек для соответствия именам файлов длины 15, не очень эффективно.

Наконец, если Вы хотите проигнорировать расширение и соответствовать только имени файла, сделайте это (как @slm предложенный):

find . -type f | grep -P '/.{1}\.'

Однако это также найдет файлы как a.bo.go. Это лучше, если Ваши имена файлов могут содержать больше чем один . :

find . -type f | grep -P '/.{1}\.[^.]+$'

Примечание: Решение выше предполагает, что у Вас есть относительно нормальные имена файлов, которые не содержат символы новой строки и т.д. Это также рассчитает не, игнорируют пробелы в именах файлов при вычислении длины, которая не могла бы быть тем, что Вы хотите. Если любой из них является проблемой, сообщите мне, и я обновлю свой ответ.

3
27.01.2020, 20:01

Вы не указываете, но если файлы в структуре каталогов, можно использовать find определять местоположение файлов, которые являются длиной 1, с помощью grep:

$ find . -type f  | grep -P '/.{1}\.'

Пример

$ find . -type f  | grep -P '/.{1}\.' | head -10
./util-linux-2.19/include/c.h
./88366/a.bash
./89186/a.bash
./89563/b.txt
./89563/a.txt
./89563/c.txt
./89563/d.txt
./91734/2.c
./91734/4.c
./91734/1.c
1
27.01.2020, 20:01

Я использовал бы что-то вроде этого.

find . -type f -name "?.go"

Таким образом, если Вы помещаете два"?" затем Вы ищете имена файлов с двумя символами и расширением.

1
27.01.2020, 20:01

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

find /var/log -iname "*.err" 

для yor использования случая:

find yourpath -type f -a -name "?.go"

Необходимо заменить реальный путь yourpath, -a средства And -type f средства, что Вы только ищете регулярные файлы.

? в Ваших средствах запроса один charachter, такой как DOS, если Вы вспоминаете.

0
27.01.2020, 20:01

ls ?.* должны дать желаемый результат.

-1
27.01.2020, 20:01

Если вы просто хотите найти имена файлов, вы можете использовать следующую команду:

find -exec basename '{}' ';' | egrep '^.{100,}$'

Это запустит find , извлекая имя файла или каталога с помощью basename а затем найдите любое имя файла или имя каталога, содержащее не менее 100 символов. Если вы хотите найти имя файла точной длины, используйте {100} вместо {100,} .

Если вы хотите найти имена файлов, включая путь, сделайте следующее:

find | egrep '/[^/]{100,}$'

Это вернет имя файла, включая относительный путь к тому месту, где вы запустили команду поиска.

8
27.01.2020, 20:01

Вот рабочее решение с использованием ls, хотя оно немного глупое. Он в основном создает строку, состоящую из вопросительных знаков, которые соответствуют желаемой длине имени файла, а затем позволяет использовать расширение оболочки в качестве подстановочного знака, передавая полученные имена файлов команде ls(и любым переключателям, которые вы ей указали. имен файлов, конечно -например,-l):

# Tested on CentOS 7

###############################
# With a fixed length (of 32) #
###############################
ls $(for i in {1..32};do echo -n '?';done)

##########################
# With a variable length #
##########################
# Set the filename length (or get it from elsewhere)
declare -x filename_len=32

# The following command can be employed
ls $(eval "for i in {1..$filename_len};do echo -n '?';done")

# Or, because eval is considered evil, the better alternative
ls $(seq -s ' ' 1 $filename_len | sed 's/[[:digit:]]\+ \?/?/g')

# Many other approaches can be used to do something similar
# (e.g., perl, etc...) to generate the question marks
ls $(perl -e 'print "?"x$ENV{filename_len}')
# If you're bothered by the quotes in the above around the question
# mark, since no interpolation is needed, you can change:
# "?" to '"'?'"'  - in this case, I'd leave the quotes for clarity.

unset filename_len

Одно предостережение заключается в том, что результирующий список имен файлов может быть длиннее, чем позволяет оболочка, и это следует учитывать. Вот почему подход find/xargs, как правило, лучше всего подходит, если количество файлов не ограничено или неизвестно.

0
04.11.2020, 17:32

Если у вас есть GNU find, вы можете просто выполнить:

find. -type f -regextype 'posix-basic' -iregex '.*/.\{1\}\.go$'
./a.go
./dir1/b.go
./dir2/subdir1/subdir2/a.go

find. -type f -regextype 'egrep' -iregex '.*/.{2}\.go$'
./ab.go
./dir1/zx.go
./dir2/subdir1/subdir2/xo.go

вы можете использовать различные -regextypeв зависимости от ваших потребностей.

valid types are ‘findutils-default’, ‘awk’, ‘egrep’, ‘ed’, ‘emacs’, ‘gnu-awk’, ‘grep’, ‘posix-awk’, ‘posix-basic’, ‘posix-egrep’, ‘posix-extended’, ‘posix-minimal-basic’, ‘sed’.

1
04.11.2020, 18:36

Теги

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