Форум русскоязычного сообщества Ubuntu


Увидели сообщение с непонятной ссылкой, спам, непристойность или оскорбление?
Воспользуйтесь ссылкой «Сообщить модератору» рядом с сообщением!

Автор Тема: Как решить задачу перемещения файлов из множества директорий в одну?  (Прочитано 3255 раз)

0 Пользователей и 1 Гость просматривают эту тему.

adawdp

  • Автор темы
  • Гость
2015 Nov 25; 08:49 AM; Oakville, ON, Canada.

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

— Задача: собрать все файлы в одну директорию, файлы с одинаковыми именами переименовать.

— Nautilus это не делает. Возможно есть плагин, помнится в Windows в TK что-то похожее было…

— Однажды я с помощью “словаря” и путём приставания к программисту :) создал вот такой скрипт:

Код: (bash) [Выделить]
#!/bin/bash

# ./zxcv.sh qq ww  → команда, где „qq“ директория с файлами и поддиректориями …
# а „ww“ директория назначения …
# собрать файлы в одну директорию из  директории с поддириекториями …
# файлы с одинаковыми именами должны  быть переименованы …

# rename: присоединяет char к имени из filename
#         (до расширения, если оно есть)
# rename(filename, char) -> <name><char>[<ext>]
rename()
{
    local filename=$1 char=$2
    echo "$filename" | sed 's/^\([^.]*\)/\1'$char'/'
}

[ $# -eq 2 ] || {
    echo "usage: `basename $0` srcdir dstdir" 1>&2
    exit 1
}

srcdir=$1
dstdir=$2

[ -d "$srcdir" -a -d "$dstdir" ] || {
    echo "error: dir doesn't exist" 1>&2
    exit 1
}

find "$srcdir" -type f | sort | while read line; do
    srcfile="$line"
    dstfile="$dstdir/`basename "$line"`"
    while [ -f "$dstfile" ]; do
        dstfile=`rename "$dstfile" "_"`
    done
    echo "moving: $srcfile -> $dstfile"
    /bin/mv "$srcfile" "$dstfile" || {
        echo "error: can't move $srcfile to $dstfile" 1>&2
        exit 1
    }
done

exit 0

— Хотелось бы услышать кто и как решает подобные проблемы и нет ли случайно плагина к Nautilus или может это делает какой-то другой файловый менеджер, а может существует вообще программа с графическим интерфейсом. Задача ведь довольно частая, а когда директорий много вручную это довольно трудоёмко.

kononvaler

  • Автор темы
  • Гость
я использую rsync для автоматизации подобных задач.

adawdp

  • Автор темы
  • Гость
2015 Nov 25; 02:18 PM; Oakville, ON, Canada.

— Я правильно, kononvaler, Вас понял, что речь идёт о программе rsync которая копирует и синхронизирует файлы между локальной и удалённой машинами и наоборот?

— И как конкретно, положим выполнить описанную мной выше задачу?

Оффлайн Cxms

  • Активист
  • *
  • Сообщений: 407
    • Просмотр профиля
Можно добавить пункт "Копировать все файлы в" в контекстное меню Nautilus при клике на директорию.
И немного модифицировав прописать этот скрипт для выполнения копирования.
Далее при нажатии появится окошко с полем для ввода пути к директории куда будут скопированы файлы.

kononvaler

  • Автор темы
  • Гость
Правильно поняли, речь идет об утилите rsync, но
Цитировать
которая копирует и синхронизирует файлы между локальной и удалённой машинами и наоборот
вы мне кажется не совсем правильно понимаете.
Этой командой можно замечательно скопировать файлы и на локальной машине. И не только скопировать, но и переместить, проверить, заменить на новые и т.п.  настолько большое количество ключей у нее предусмотрено.
И могли бы вы поподробнее описать вашу задачу? Навскидку это выглядит так:
rsync -vr --progress   откуда/ куда  && rsync -r --delete /var/empty/ откуда
первая часть команды скопирует все файлы , вторая удалит все на источнике (либо --remove-source-files  , но останутся пустые каталоги)
эта команда позволяет скопировать файлы из заданного списка каталогов в назначенный "куда"
rsync -vr --progress  --files-from=files.txt --no-relative Myfoto/ test
содержимое files.txt вида:
откуда/дир1/
откуда/дир2/дир3/
на конце должен быть слеш , чтобы копировалось содержимое каталога без самого каталога.
rsync проверяет одинаковость файлов и копирует только измененные. для того чтобы сохранить разный файл с одинаковым названием от источника, можно задать ключ со специальной маской, например по времени.
« Последнее редактирование: 26 Ноября 2015, 10:09:21 от kononvaler »

adawdp

  • Автор темы
  • Гость
2015 Nov 26; 08:11 AM; Oakville, ON, Canada.

Cxms, понятно, спасибо, в сценариях Ubuntu Tweak такого я не нашёл, наверное какой-то отдельный плагин, не знаю будет ли работать в 14.04 после всех переработок и “обрезаний :)” этого файлового менеджера. Подскажите, если что, что за это за плагин или алгоритм правки контекстного меню Nautilus.

— Спасибо, kononvaler за развёрнутый ответ, выглядит очень надёжно, я попробовал, но всё же для большего уровня автоматизации чтобы каждый раз много не писать или скрипт или какую-то шпаргалку нужно сделать.

Оффлайн Azure

  • Почётный модератор
  • Старожил
  • *
  • Сообщений: 6017
  • Windows10, i3wm on Debian9, Manjaro20.0
    • Просмотр профиля
Если Вы распишите, каким образом
файлы с одинаковыми именами переименовать
, то возможно мы напишем ма-а-а-ленький скриптик, который всё сделает. (обычно переименовывают название субдиректории + имя_файла)
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

kononvaler

  • Автор темы
  • Гость
Если Вы распишите, каким образом
файлы с одинаковыми именами переименовать
, то возможно мы напишем ма-а-а-ленький скриптик, который всё сделает. (обычно переименовывают название субдиректории + имя_файла)
rsync  проверяет не только файл с одинаковым именем, а является ли файл одинаковым (по умолчанию по md5, для ускорения можно указать ключ --size-only, тогда будет сравниваться только размер) и можно с ключем --backup (или -b) и с использованием ключа --suffix задать переименование файла в месте назначения по шаблону этого самого суффикса, например:
rsync -ab --suffix="date '+%Y-%m-%d_%H:%M%S'"  source/  destination
При обнаружении в директории назначения не такой-же файл с одинаковым названием будет переименован добавлением к имени текущей даты-времени.

Оффлайн Cxms

  • Активист
  • *
  • Сообщений: 407
    • Просмотр профиля
adawdp,
Я создавал новые пункты в pcmanfm в Lubuntu.
Есть варианты и для Nautilus:
Но может вам подойдет выриант с zenity?
1. Скрипт будет запускатся двойным кликом, потом будет выбор:
2. директории источника:
zenity --file-selection --title="Выберите директорию файлы из которой будут перемещены" --directory3. директории назначения:
zenity --file-selection --title="Выберите директорию куда будут перемещены файлы" --directory4. Перемещение файлов и сообщение о статусе выполнения.
« Последнее редактирование: 26 Ноября 2015, 21:17:36 от Cxms »

adawdp

  • Автор темы
  • Гость
2015 Nov 26; 01:44 PM; Oakville, ON, Canada.

— Я Вас приветствую, Azure, там в приведенном мною скрипте файлы с одинаковыми именами переименовываются, подставляется „_“…

— Ради этого то в общем всё и затевалось, например много разных картинок с одинаковыми названиями, а после перемещений может остаться одна, если скрипт не будет менять имена.

— Безусловно rsync мощная штука, охватывает в принципе все мои потребности, уже проверил, просто всё время нужно заглядывать в руководство подставляя ключи, не знаком был раньше с этой программой…

— Новый скрипт буду писать используя эту программу, но это уже другая тема…

Cxms, спасибо я понял, попробую.

Оффлайн Cxms

  • Активист
  • *
  • Сообщений: 407
    • Просмотр профиля
adawdp,
Вот:
mv_files_to_dir.sh
Код: (bash) [Выделить]
#!/bin/bash

cd "$HOME"
SRC_DIR="$(zenity --file-selection --title="Выберите директорию из которой будут перемещены файлы" --directory)"
[ -z "$SRC_DIR" ] && exit 0
[ -d "$SRC_DIR" ] || { zenity --error --title="Перемещение файлов" --text="Директория $SRC_DIR не найдена."; exit; }
NOT_WRTBL_FLS="$(find "$SRC_DIR" ! -writable 2>/dev/null)"
[ -z "$NOT_WRTBL_FLS" ] || { zenity --error --title="Перемещение файлов" --text="В директории $SRC_DIR есть не доступные для записи файлы:\n$NOT_WRTBL_FLS"; exit; }

DEST_DIR="$(zenity --file-selection --title="Выберите директорию куда будут перемещены файлы" --directory)"
[ -z "$DEST_DIR" ] && exit 0
[ -d "$DEST_DIR" ] || { zenity --error --title="Перемещение файлов" --text="Директория $DEST_DIR не найдена."; exit; }
[ -w "$DEST_DIR" ] || { zenity --error --title="Перемещение файлов" --text="Директория $DEST_DIR не доступна для записи."; exit; }

CHAR="_"
ALL_SRC_FILES="$(find "$SRC_DIR" -type f | sort)"
ALL_SRC_FILES_CNT=$(echo "$ALL_SRC_FILES" | wc -l)

{
echo "Перемещение файлов..."
IFS=$'\n'
for SRC_FILE in $ALL_SRC_FILES; do
DEST_FILE="$DEST_DIR/$(basename -z "$SRC_FILE")"
while [ -f "$DEST_FILE" ]; do
echo -n "Переименован файл \"$DEST_FILE\" в "
DEST_FILE="$(echo -n "$DEST_FILE" | sed 's/^\([^.]*\)/\1'$CHAR'/')"
echo "\"$DEST_FILE\""
done
mv "$SRC_FILE" "$DEST_FILE" && let N+=1 || echo "Ошибка при перемещении файла $SRC_FILE"
done
echo "Перемещено $N файлов из $ALL_SRC_FILES_CNT."
} | zenity --text-info --width=750 --height=450 --title="Перемещение файлов"

Для ввода и вывода используется zenity.
Запускать можно просто двойным кликом. (Нужно добавить права на запуск)
Скрипт работает.
« Последнее редактирование: 27 Ноября 2015, 00:18:35 от Cxms »

adawdp

  • Автор темы
  • Гость
2015 Nov 26; 04:40 PM

— Спасибо, Cxms, у меня тоже работает…

 

Страница сгенерирована за 0.066 секунд. Запросов: 25.