2

Давайте предположим, что у меня есть такие файлы:

out-1.avi

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

out-1.avi
out-2.avi
out-3.avi
etc.

Редактировать То, что мне нужно сделать, это получить следующее имя файла для сценария записи веб-камеры, чтобы он не переписывался!

5 ответов5

5

Я не знаю контекст, но следующий цикл содержит все элементы, которые вам понадобятся:

n=0; while (($n < 10)); do ((++n)); echo name=out-$n.avi; done

Это перечислит первые 10 файлов в вашей последовательности.

После вашего редактирования я вижу несколько ответов.

Простая модификация моего оригинального цикла:

n=1; while [ -f out-$n.avi ]; do ((++n)); done; echo name=out-$n.avi

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

Более эффективный ответ - сохранить последний номер файла в своем собственном файле:

n=`line<avicount.text`; ((++n)); echo "$n">avicount.text; echo name=out-$n.avi

Этот сценарий будет генерировать новое имя каждый раз, когда он вызывается, но использует avicount.text всегда оставаясь в синхронизации с используемыми файлами и именами.

Лучшее решение - использовать метку времени вместо порядкового номера:

echo name=out-`date +%Y%M%d%H%m%S`.avi

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

1
#!/bin/bash
LAST=$(find . -maxdepth 1 -name "*.avi" -type f -printf "%p\n" | sed -e s/.\\/out-//g -e s/.avi//g | sort -g | tail -1)
touch out-$(($LAST + 1)).avi
  • Первая строка выбирает последний измененный avi-файл в каталоге (без рекурсии) и извлекает число из его имени.
  • Во второй строке добавьте 1 к предыдущему имени и сгенерируйте файл.
0

Предполагая, что у вас не много файлов в каталоге видео (в этом случае этот подход не очень эффективен), может помочь простое кодовое кодирование:

MAX=1000;
PREFIX="out-"
SUFFIX=".avi"

for i in `seq 1 $MAX` ; do
    file="${PREFIX}${i}${SUFFIX}"

    if [ ! -e $file ] ; then
        break;
    fi
done

# this is the next available file name
echo $file

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

0

Решение @jherran должно соответствовать вашим потребностям. Если вы просто хотите, чтобы скрипт дал вам следующее имя файла, а не создавал его для вас, измените "touch" на "echo" в конце его скрипта.

Тем не менее, это будет все медленнее и медленнее, когда вы добавляете много файлов. Если вам нужны последовательные числа, вы можете просто записать текущий номер в файл, затем прочитать его обратно перед записью следующего файла, записать новый номер и записать свой файл. Я предоставил пример кода для этого ниже.

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

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

#!/usr/bin/sh

if [ -f counter.txt ]; then
{
   VAL=`cat counter.txt`
   echo "out-$VAL.avi"
   VAL=`expr $VAL + 1`
   echo "$VAL" > counter.txt
   exit 0
}
fi
echo "out-1.avi"
echo "2" > counter.txt
exit 0

Или, если вы хотите согласиться с моим предложением штампов даты для уникальности и сортировки, просто попросите вашу программу записи файлов получить вывод этой команды:

 date +%F-%T

или любой детализации дат и времени, которые вы считаете полезными. Вышесказанное даст вам что-то вроде этого:

2014-12-01-16:41:33

Ударьте «.avi» в конце, и у вас есть временные имена файлов, вплоть до второго.

0

Вы можете использовать seq для генерации значений, затем touch чтобы создать файлы.

for n in $(seq 1 5)
do
    touch out-${n}.avi
done

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