Как я могу получить первое соответствие от подстановочного расширения?

Сначала попытайтесь найти разрешение, которое Вы имеете для этой папки и ее последующих файлов с помощью этой команды:

ls -lrt

Попытайтесь видеть, существует ли липкий бит, связанный с ним. Затем изменитесь на корневое использование:

sudo su

И затем дайте разрешение как:

chmod +rwx filename

Это должно сделать это.

41
18.09.2014, 23:57
6 ответов

Попробуйте:

for i in *.txt; do printf '%s\n' "$i"; break; done
1.txt

Обратите внимание, что расширение имени файла отсортировано в соответствии с действующей коллекционной последовательностью в текущей локали.

6
27.01.2020, 19:35

В zsh используйте квалификатор [1] glob . Обратите внимание, что даже несмотря на то, что этот особый случай возвращает не более одного совпадения, он по-прежнему является списком, а глобусы не раскрываются в контекстах, которые ожидают одно слово, например присваивания (не считая присваивания массива).

echo *.txt([1])

В ksh или bash вы можете поместить весь список совпадений в массив и использовать первый элемент.

tmp=(*.txt)
echo "${tmp[0]}"

В любой оболочке вы можете установить позиционные параметры и использовать первый.

set -- *.txt
echo "$1"

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

echo "$(set -- *.txt; echo "$1")"

Вы также можете использовать функцию, которая имеет собственный набор позиционных параметров.

set_to_first () {
  eval "$1=\"\$2\""
}
set_to_first f *.txt
echo "$f"
21
27.01.2020, 19:35

Простое решение:

sh -c 'echo "$1"' sh *.txt

Или используйте printf, если хотите.

3
27.01.2020, 19:35

Одним из надежных способов в bash является расширение в массив, и вывод только первого элемента:

pattern="*.txt"
files=( $pattern )
echo "${files[0]}"  # printf is safer!

(Можно даже просто echo $files, пропущенный индекс обрабатывается как [0])

Это безопасно обрабатывает пробел/таб/новострочные и другие метасимволы при расширении имён файлов. Обратите внимание, что настройки локали на самом деле могут изменить то, что является "первым".

Это также можно сделать интерактивно с помощью функции завершения bash :

_echo() {
    local cur=${COMP_WORDS[COMP_CWORD]}   # string to expand

    if compgen -G "$cur*" > /dev/null; then
        local files=( ${cur:+$cur*} )   # don't expand empty input as *
        [ ${#files} -ge 1 ] && COMPREPLY=( "${files[0]}" )
    fi
}
complete -o bashdefault -F _echo echo

Это связывает функцию _echo для завершения аргументов с командой echo (отменяя обычное завершение). В код выше добавлено дополнительное "*", можно просто нажать клавишу табуляции на частичном имени файла и надеяться, что все получится правильно.

Код является немного запутанным, вместо того, чтобы устанавливать или предполагать nullglob (shopt -s nullglob), мы проверяем, что compgen -G может расширить глобус до некоторых совпадений, затем мы безопасно расширяем глобус до массива, и, наконец, устанавливаем COMPREPLY так, чтобы кавычки были надежными.

Вы можете частично сделать это (программно расширить глобус) с помощью bash's compgen -G, но это не является робастным, так как выводит нецитируемые данные в stdout.

Как обычно, завершение довольно чревато, это нарушает завершение других вещей, в том числе и переменных окружения (подробности эмуляции поведения по умолчанию см. в функции _bash_def_completion() здесь here).

Также можно использовать compgen вне функции завершения:

files=( $(compgen -W "$pattern") )

Следует отметить, что "~" - это не глобус, он обрабатывается bash на отдельном этапе расширения, также как и $variables и другие расширения. compgen -G просто производит глобирование имен файлов, но compgen -W дает вам все расширения по умолчанию bash, хотя возможно слишком много расширений (включая `` и $()). В отличие от -G, -W - безопасно цитируется (я не могу объяснить это несоответствие). Так как целью -W является расширение лексем, это означает, что он будет расширять "a" до "a", даже если такого файла не существует, так что, возможно, это не идеально.

Это легче понять, но может иметь нежелательные побочные эффекты:

_echo() {
    local cur=${COMP_WORDS[COMP_CWORD]}
    local files=( $(compgen -W "$cur") ) 
    printf -v COMPREPLY %q "${files[0]}"  
}

Затем:

коснитесь $'curious \n имени файла'

echo curious*tab

Обратите внимание на использование printf %q, чтобы безопасно цитировать значения.

Последняя опция - использование 0-раздельного вывода с утилитами GNU (смотрите bash FAQ):

pattern="*.txt"
while IFS= read -r -d $'\0' filename; do 
    printf '%q' "$filename"; 
    break; 
done < <(find . -maxdepth 1 -name "$pattern" -printf "%f\0" | sort -z )

Эта опция дает вам немного больше контроля над порядком сортировки (порядок при расширении глобуса будет зависеть от вашей локали/LC_COLLATE и может складываться, а может и не складываться), но в остальном является довольно большим молотком для такой маленькой проблемы ;-)

.
26
27.01.2020, 19:35

Я только что наткнулся на этот старый вопрос, задаваясь тем же вопросом. Я закончил с этим:

echo $(ls *.txt | head -n1)

Вы можете, конечно, заменить headна tailи -n1на любое другое число.


Описанное выше не будет работать, если вы работаете с файлами, в имени которых есть символы новой строки. Для работы с новыми строками вы можете использовать любой из этих:

  • ls -b *.txt | head -n1 | sed -E 's/\\n/\n/g'(Не работает на BSD)
  • ls -b *.txt | head -n1 | sed -e 's/\\n/\'$'\n/g'
  • ls -b *.txt | head -n1 | perl -pe 's/\\n/\n/g'
  • echo -e "$(ls -b *.txt | head -n1)"(Работает с любым специальным символом)
4
27.01.2020, 19:35

Вариант использования, с которым я часто сталкиваюсь, заключается в определении либо верхнего/нижнего каталога после расширения glob (, например. каталог, полный версий SDK или инструментов сборки ). В этой ситуации я обычно хочу сохранить это имя каталога в переменной для использования в нескольких местах в сценарии оболочки.

Эта команда обычно делает это за меня:

export SDK_DIR=$(dirname /path/to/versioned/sdks/*/. | tail -n1)

Отказ от ответственности :Расширение Glob не будет сортировать ваши папки по семестру; вас предупредили. Это замечательно, если у вас есть Dockerfileтолько одна версия каталога, но эта версия каталогов может варьироваться от изображения к изображению

-1
27.01.2020, 19:35

Теги

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