Подстановочный знак Bash не расширяется

Все это можно сделать как одно целое.

for i in *.* ; do mv "$i" "${i%.*}_$(date --reference "$i" +%Y%m%dT%H%M).${i##*.}"; done

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

for i in *.* ; do mv "$i" "${i%.*}_$(date --reference "$i" +%s).${i##*.}"; done

Эта проверка безопасности предназначена только для работы с файлами, имена которых содержат точки; он правильно обрабатывает файлы с местами в именах; и предполагает (как это обычно бывает), что поле, разделяющее ПОСЛЕДНИЕ точки, является расширением, а не поле, разделяющее ПЕРВЫЕ точки, является именем файла, а остальное является расширением.

Зачет muru для бита -привязки ; Я не знал об этом варианте.

-121--70032-

печать :

  • «Печать» сама по себе печатает входную строку.
  • «Print» с одним аргументом печатает аргумент.
  • «Print» с несколькими аргументами печатает все аргументы, разделенные пробелами (или другими указанными OFS), когда аргументы разделены запятыми, или объединяются, когда аргументы разделены местами.

printf :

Функция «printf ()» (отформатированная печать) намного гибче и сложнее. Имеет синтаксис

 printf(,)

Разница :

Разница между printf и print является аргументом формата. Это выражение, значение которого принимается как последовательность; определяет способ вывода каждого из других аргументов. Она называется последовательностью формата.

Ссылается на здесь и здесь

-121--53989-

Этот фрагмент сценария оболочки создает расширенное регулярное выражение (с / символами, которые соответствующим образом удалены), содержащее все дни с прошлого понедельника по следующее воскресенье, в формате YYYY/MM/DD Затем с помощью grep выполняется поиск в файле журнала.

DAYS=$(for D in {0..6} ; do 
           date -d "last monday + $D days" +'%Y\\/%m\\/%d'
       done | xargs | 
       sed -e 's/ /|/g'
      )

REGEX="^($DAYS) "

grep -E "$REGEX" logfile.txt

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

REGEX="^\($DAYS\) "
REGEX=$(printf "%s" "$REGEX" | sed -e 's/\([|]\)/\\\1/g')

grep "$REGEX" logfile.txt

Другой вариант - использовать опции grep -F (фиксированная строка) и -f (файл) с возможностью подстановки процесса оболочки , например:

DAYS=$(for D in {0..6} ; do 
           date -d "last monday + $D days" +'%Y/%m/%d'
       done )

grep -F -f <(echo "$DAYS") logfile.txt

или даже

grep -F -f <( for D in {0..6} ; do 
              date -d "last monday + $D days" +'%Y/%m/%d'
              done ) logfile.txt

ПРИМЕЧАНИЕ: эти последние две версии будут совпадать на дату в этом формате в любом месте строки, а не только в начале строки. с образцом, который вы дали, это вряд ли будет проблемой.

4
19.06.2018, 23:28
3 ответа

*.d расширяется до файлов, имена которых заканчиваются на .d.

С помощью zshможно сделать:

files=(*)
mkdir -- $^files.d

Или с анонимной функцией:

() { mkdir -- $^argv.d; } *

Или добавление суффикса через квалификатор eglob:

mkdir -- *(e{REPLY+=.d})

Или модификатор истории :s, примененный к глобусам (с histsubstpatternдля %, означающим конец):

set -o histsubstpattern
mkdir -- *(:s/%/.d)

Вы также можете не делать этого для файлов, которые уже являются каталогами или символическими ссылками на каталоги, добавив квалификатор ^-/glob:

files=(*(^-/))
mkdir -- $^files.d

(обратите внимание, что zshне имеет такой неправильной функции, как другие Bourne -, такие как оболочки, в которых шаблоны, которые не совпадают, передаются как -, поэтому mkdir *.dне будет создавать каталог *.d, если в текущем каталоге не было файла, соответствующего *.d, вместо этого команда прервалась бы с ошибкой)

2
27.01.2020, 20:44

Вместо for foo in bar; do baz; doneрешения я бы предложил:

find. -maxdepth 1 -type f -print0|xargs -0 -I file mkdir file.d

2
27.01.2020, 20:44

Подстановочный знак всегда расширяется до существующих имен.

Ваша команда mkdir *не удалась, потому что имена, которые раскрываются *, уже существуют.

Ваша команда mkdir *.d"сбой", потому что *.dне соответствует ни одному существующему имени. Таким образом, по умолчанию шаблон остается нераскрытым 1 и создается каталог с именем *.d. Вы можете удалить это с помощью rmdir '*.d'.

Создать каталог для каждого обычного файла в текущем каталоге, чтобы новые каталоги имели то же имя, что и файлы, но с суффиксом .d:

for name in./*; do
    if [ -f "$name" ]; then
        # this is a regular file (or a symlink to one), create directory
        mkdir "$name.d"
    fi
done

или, для тех, кто любит "один -лайнеров",

for n in./*; do [ -f "$n" ] && mkdir "$n.d"; done

В bashвы также можете сделать

names=(./* )
mkdir "${names[@]/%/.d}"

но это не проверяет, являются ли вещи, в которые расширяется glob, обычными файлами или чем-то еще.

Начальный ./в приведенных выше командах предназначен для защиты от имен файлов, содержащих начальный дефис(-)в именах файлов. В противном случае тире и символы, следующие за ним, интерпретировались бы как опции для mkdir.


1Некоторые оболочки имеют опцию оболочки nullglob, которая приводит к тому, что не совпадающие -подстановочные знаки оболочки заменяются пустой строкой. В bashэто включается с помощью shopt -s nullglob.

20
27.01.2020, 20:44

Теги

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