Файлы копии того же имени в тот же каталог

У меня есть большое количество папок с названным файлом genome.txt то, что я должен cp в ту же папку. Я пытаюсь выяснить, как я могу сделать это так, файлы похожи genome1.txt, genome2.txt, и т.д. Я ищу простое решение этого.

4
задан 23 March 2017 в 00:13

1 ответ

Сценарий оболочки и его использование

Это может быть сделано с простым сценарием оболочки, который использует find ...|while read var ; do ... done структура (очень распространенный имея дело с именами файлов). Сценарий удара ниже воздействует на текущий (самый важный) каталог и берет отдельный аргумент для места назначения.

#!/bin/bash
find -name "genome.txt" -print0 | while IFS= read -r -d '' path
do
    base=$(basename --suffix=".txt"  "$path")
    new_path="${1%/}"/"$base"$counter".txt"
    echo "$path" "$new_path"
    counter=$(( $counter +1 ))
done

>>> ПРИМЕЧАНИЕ <<<: использование сценария echo просто для тестирования. Когда Вы удовлетворены получающимися путями, заменой echo с mv перемещать все имена файлов или cp скопировать все имена файлов.

Пример:

bash-4.3$ tree
.
├── destination
├── dir1
│  └── genome.txt
├── dir2
│  └── genome.txt
├── dir3
│  └── genome.txt
└── move_enumerated.sh

4 directories, 4 files
bash-4.3$ ./move_enumerated.sh  ./destination
./dir2/genome.txt ./destination/genome.txt
./dir3/genome.txt ./destination/genome1.txt
./dir1/genome.txt ./destination/genome2.txt

Улучшение сценария для большей гибкости

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

#!/bin/bash
find "$2"  -name "$1" -print0 | while IFS= read -r -d '' path
do
    base=$(basename --suffix=".txt"  "$path")
    new_path="${3%/}"/"$base"$counter".txt"
    echo "$path" "$new_path"
    counter=$(( $counter +1 ))
done

Тестовый прогон:

bash-4.3$ ./move_enumerated.sh "genome.txt"  "./testdir" "./testdir/destination"
./testdir/dir2/genome.txt ./testdir/destination/genome.txt
./testdir/dir3/genome.txt ./testdir/destination/genome1.txt
./testdir/dir1/genome.txt ./testdir/destination/genome2.txt

Синтаксис и теория операции

По всему сценарию использует command | while read variable ; do ... done структура. Это - очень общий подход, и он часто используется, чтобы не иметь дело с ls и трудные имена файлов, которые могут повредить сценарии.

На левой стороне канала мы имеем find команда, которая берет каталог в качестве аргумента (и если это не дано, GNU find то, которое используется в Linux, принимает . - текущий рабочий каталог). Другие опции включают -name который является определенным именем файла, которое мы ищем, и -print0 который используется для вывода результатов, как разграничено через непечатаемый \0 символ. Это часто используется, чтобы не разделять на новой строке или других символах, потому что те символы могут потенциально появиться в самом имени файла и в результате повредить сценарий.

На правой стороне канала мы имеем while IFS= read -r -d '' ; do . . . done структура. while цикл с read встроенная оболочка часто привыкла к реальному stdin вход, который в этом случае прибывает из канала. IFS= -r и -d '' необходимы, чтобы гарантировать, чтобы мы получили имена файлов безопасно и распознали, что каждый объект разграничен с \0.

Остальная часть сценария довольно легка. Мы извлекаем базовое имя использования файла basename команда. Так как в этом случае мы имеем дело конкретно с известным расширением и ожидаем иметь единственную точку в имени файла, мы можем использовать --suffix=".txt" разделять ту часть, уезжая genome часть. Мы затем создаем новый путь к файлу через присоединение к месту назначения, базовому имени и переменной счетчика. Заметьте, что мы используем расширение параметра с "${3%/}" аргумент (папка назначения) в нашем улучшенном сценарии. Это сделано, чтобы гарантировать, что независимо от того, добавил ли пользователь / символ в командной строке ( ./destination или ./destination/ ), мы извлекаем только пустое имя каталога и присоединяемся к нему через различный / с базовым именем. Заметьте также это counter переменная не установлена первоначально, таким образом, первое имя файла, которое мы получаем, будет просто genome.txt После, чем, переменная счетчика будет увеличена и таким образом создана и обнаружится, когда мы будем иметь дело с другими именами файлов.

Для большего количества информации считайте Имена файлов и Пути в Shell: Как сделать это Правильно.

4
ответ дан 1 December 2019 в 09:45

Другие вопросы по тегам:

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