Генерировать новое название перемещенного файла для предотвращения перезаписи?

Информация является автономной программой, которая подражает встроенному интерфейсу документации Emacs. Emacs не прибывает из мира Unix, и некоторые его привязки клавиш отличаются от традиционной привязки Unix. В частности, Ctrl+C является назад к верхнему уровню ключом под Unix, но под Emacs, это - Ctrl+G (который является также символом звонковой сигнализации, когда он испускается терминалом). Поэтому нажмите Ctrl+G в Menu item: подсказка. Ctrl+C выходит из Информации, потому что то, что это делает в Emacs (настраиваемый префикс) не применимо к Информации, таким образом, Информация дает ему Unix, означающий вместо этого (закройте текущую программу).

8
07.09.2013, 01:38
3 ответа

Принятие Вас имеет оболочку POSIX, можно сделать это:

mv() {
        eval "DEST=\${$#}" #The destination is the last positional parameter
        if [ -e "$DEST" ] && ! [ -d "$DEST" ];then
                PREFIX=${DEST%.*}
                COUNT=1
                EXT=${DEST##*.}
                args= i=1
                while [ $i -lt $# ]; do args="$args \"\${$i}\"" i=$((i+1)); done
                DEST="$NAME-"$(printf "%03d" $COUNT)".$EXT"
                while [ -e "$DEST" ];do
                    COUNT=$((COUNT+1))
                    DEST="$NAME-"$(printf "%03d" $COUNT)".$EXT"
                done
                eval "command mv $args \"\$DEST\""
        else
                command mv "$@"
        fi
}

Как использовать это

Это - функция, так сохраните ее в Вашем ~/.bashrc и назовите его, поскольку Вы были бы нормальное mv.

Что это делает

  • Хранит путь к оригиналу mv исполняемый файл в MV переменная
  • Получает последний аргумент, с которым это назвали в переменную DEST
  • Если DEST существует и не каталог, эта функция предполагает, что Ваш переименовывать, пытается ударить файл
  • Это затем извлекает префикс заключительного имени (что-либо перед финалом ., который отмечает расширение), расширение (что-либо после финала .), количество (если таковые имеются что-либо в префиксе после финала -).
  • Извлеченное количество обнуляется, если никакое количество не было найдено иначе, оно установлено на количество, найденное на предыдущем шаге.
  • Текущее количество увеличено
  • Функция затем называет себя со всеми исходными аргументами (переключатели + имена файлов) минус последний и добавляет новое имя файла вместо последнего аргумента в первоначальном вызове. Новое имя является старым названием, но с 3 счетчиками цифры (с наполнением нуля) добавленный перед расширением.
  • Функция является рекурсивной потому что, если Вы говорили mv a.txt b.txt это сначала попробует mv a.txt b-001.txt. Это затем mv вызов должен также быть самой функцией потому что если b-001.txt также существует, мы хотим продолжать увеличивать счетчик, пока мы не находим новое имя файла, которое не существует.
  • Если заключительный аргумент не существует или является каталогом, оригиналом mv исполняемый файл называют с Вашими исходными аргументами.

Протесты

  • Количество раз можно неоднократно пытаться ударить существующий файл, зависит от длины счетчика (999 раз в этом случае). Можно выбрать много цифр, который охватывает предел inode на файловую систему, чтобы гарантировать, что это будет работать столько, сколько Вы можете создать файлы.
  • При попытке ударить файл, имя которого является аналогичным foo-001.txt, это будет перемещено в foo-001-001.txt.

Примечания

  • Для изменения шаблона именования изменитесь 3 в printf оператор к тому, что Вы любите.
  • Этот код был протестирован
  • Это очень упрощенно, и я уверен, что будут пограничные случаи, где это терпит полный провал. Я рад попытаться зафиксировать их для Вас, если Вы находите кого-либо. Тем временем не пробуйте это на производственной машине.
5
27.01.2020, 20:11
  • 1
    тот же ум здесь :P –  Rahul Patil 06.09.2013, 22:54
  • 2
    @RahulPatil Кроме я пытаюсь копировать поведение GUI. –  Joseph R. 06.09.2013, 22:56
  • 3
    это является большим, я еще не использовал GUI. –  Rahul Patil 06.09.2013, 22:57
  • 4
    это перезаписывает целевой файл, если это выходит, я протестировал paste.ubuntu.com/6071897 –  Rahul Patil 06.09.2013, 23:04
  • 5
    @RahulPatil, Не уверенный, что Вы говорите: в Вашем примере это определило это /tmp существующий каталог и названный /bin/mv file1 /tmp Я не вижу, где проблема. –  Joseph R. 06.09.2013, 23:06

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

Пример

Вот то, как можно создать некоторые временные имена к файлам в текущем каталоге.

$ mktemp somefile.XXXXX
somefile.kiDad

$ mktemp somefile.XXXX
somefile.MrSW

$ mktemp someotherfile.XXXXXXXXXXX
someotherfile.Um4aXKrt3lv

Это создаст файлы для Вас.

Ссылки

3
27.01.2020, 20:11
  • 1
    Нет mktemp на андроиде, но +1 от меня так или иначе, так как это - хороший ответ на хороший вопрос, мудрый U&L. –  goldilocks 06.09.2013, 23:10
  • 2
    @goldilocks - спасибо за Ваши добрые слова. Это всегда хорошо! –  slm♦ 06.09.2013, 23:11
  • 3
    @goldilocks - Вы знаете бесцеремонно, если busybox включен? Существует реализация mktemp в этом, я не знаю так много об андроиде. code.google.com/p/abb/source/browse/mktemp.c? name=upstream / … –  slm♦ 06.09.2013, 23:18
  • 4
    Похож на busybox на андроиде, требует, чтобы устройство было сделано рутинг (взломанное). Собственная оболочка /system/bin/sh и, кажется, sh совместимый - создает как if [ -w $file ] работа, mv и rename доступны - так сценарий, чтобы сделать, это только с созданным-ins должно работать там. –  goldilocks 06.09.2013, 23:52
  • 5
    @goldilocks - благодарит проверить. Что Вы заглядываете для обнаружения этого? Я хотел бы намочить ноги с андроидом, но не хочу иметь телефон/устройство. –  slm♦ 07.09.2013, 00:03

Вот альтернатива сценарию R Joseph, который не имеет ни одного из протестов! Это добавит числовой суффикс к пути (путь может быть каталогом или файлом), увеличивая суффиксное значение, пока каждый не найден, который уже не существует. Другие утилиты такой как logrotate используйте подобный шаблон, но поверните все существующие копии так, чтобы новый всегда имел '0' для суффикса. Так как это не вращение в этом смысле, я назову его dotmv. Просто помните это file.0 будет самая старая копия.

Например:

dotmv somefile.txt

Переименовывает somefile.txt somefile.txt.0, если последний не будет существовать, в этом случае это будет somefile.txt.1, и так далее. Можно перечислить больше чем один файл (dotmv this that "the other thing" и т.д.), все они будут перемещены в точку.

Я полагаю, что это - совместимый POSIX - он работает с set -o posix на ударе (но это - сомнительный тест). Я также протестировал с андроидом (боб желе 4.2.1) оболочку, и это работает там. Однако на андроиде необходимо будет изменить хижину, как обозначено или выполнено это sh dotmv - который Вы будете так или иначе, если у Вас не будет сделанного рутинг устройства, потому что нет никакого способа сделать исполняемый файл сценария иначе. Изменение хижины позволит Вам использовать exec dotmv.

#!/bin/sh
# On android change that to /system/bin/sh.

# Validate arguments
if [ $# -lt 1 ]; then
    echo "A list of one or more paths is required."
    exit 1
fi

# Checks if a path exists and can be moved.
checkPath () {
    if [ ! -e "$1" ]; then
        echo "'$1' does not exist."
        return 1;
    fi
    if [ ! -w "$1" ]; then
        echo "Cannot move '$1', permission denied."
        return 1;
    fi
    return 0;
}

# Finds a new path with numerical suffix.
getName () {
    suf=0;
    while [ -e "$1.$suf" ]
        do let suf+=1
    done
    Dest=$1.$suf
}

# Loop through arguments -- use quotes to allow spaces in paths.
while (($#)); do
    Src=$1
    Dest=$1
    shift
    checkPath "$Src"
    if [ $? -eq 0 ]; then
        getName "$Src"
        mv "$Src" "$Dest"
    fi
done

Надо надеяться, логика здесь очень проста. Это могло быть реализовано в Python, C, или любом другом Тьюринге полный процедурный язык с файловым вводом-выводом.

2
27.01.2020, 20:11

Теги

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