cp file и переименовать его, основываясь на старом имени файла?

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

input1-input2-input3

Я хотел бы скопировать этот файл и изменить input3 на input4 или что-то в этом роде, и я хочу, чтобы имя отражало это. У меня есть пытался написать простой сценарий bash, который выглядит следующим образом:

#!/bin/bash
#Inputs:{file to be copied} {solvent to change}
file=${1?No file given}
input3=${2?no input}

внесите некоторые изменения

cp file newfile

Интернет дал мне несколько советов по "внесению некоторых изменений", например е этот совет: http://www.peteryu.ca/tutorials/shellscripting/batch_rename так что моя текущая попытка выглядит так с именем файла

test-gs-xcf-Solvector.gjf

 #!/bin/bash
 
 #Inputs:{file to be copied} {solvent to change} 
 file=${1?No file given} 
 solvent=${2?no solvent given}
 
 
 filename=$(basename "$file" .gjf) ls -1 $file  | awk '{print("mv "$1 "" $1)}' | sed "s/solvent/$solvent/2" > rename_"$filename".txt 
 newfile=awk '{print $3}' rename_"$filename".txt 
 if [ -f "$newfile" ] 
 then
         echo "$newfile" > "$dir/newfile" 
 fi 
 cp "$file" "$newfile"

~

У меня это не сработало, потому что я думаю, что эта ссылка отвечает на другой вопрос.

Итак, у меня есть файл под названием:

input1-input2-input3

Я хотел бы написать сценарий bash, который будет выглядеть так:

.\bash.bash input1-input2-input3 input4

с выводом:

input1-input2-input4

Теоретически я хотел бы изменить все эти поля в будущем, но пока я хотел бы просто упростить пример.

]Спасибо вам всем! Это мой первый пост, поэтому дайте мне знать, если у меня возникнут проблемы с форматированием

1
задан 13 November 2020 в 13:26

1 ответ

Привет, Герман Барсенас :) Мы подготовили небольшой скрипт, который делает то, что вы просите в конце вопроса:

Скрипт

#!/bin/bash

# Get the input parameters
old_file=${1?No file given} 
solvent=${2?no solvent given}

# Get the basename of the file
old_file_base=$(basename $old_file '.gjf')

# Run it through awk
new_file=$(echo $old_file_base | awk -v sol=$solvent '{split($0, tmp, "-"); \
        tmp[3] = sol; print sprintf("%s-%s-%s", tmp[1], tmp[2], tmp[3])}')

# It can all be compressed into one line
# new_file=$(basename $old_file '.gjf' | awk -v sol=$solvent '{split($0, foo, "-"); \
          # foo[3] = sol; print sprintf("%s-%s-%s", foo[1], foo[2], foo[3])}')

# Work with the file...

# Uncomment to check the new filename is correct
echo $new_file

# And copy the file
# cp $old_file $new_file

Разбираем его

Мы пробовали скрипт на bash 3.2.57, и он должен работать как есть. Он просто выводит имя файла, которое будет добавлено к вновь скопированному файлу, но вы можете настроить его по своему усмотрению. Давайте посмотрим на каждый кусок.

  1. Входные параметры
old_file=${1?No file given} 
solvent=${2?no solvent given}

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

  1. Получение базового имени
old_file_base=$(basename $old_file '.gjf')

Эта часть сохранит базовое имя файла в переменной old_file_base. Этот дополнительный шаг не нужен, но мы добавили его, чтобы попытаться сделать все более понятным. Мы запускаем эту команду, чтобы скрипт работал, даже если предоставленный путь к файлу является абсолютным (т. е. он указан из корневой папки, поэтому он начинается с /. Примером абсолютного пути является / абсолютный/путь/к/foo).

  1. Запуск через awk
new_file=$(echo $old_file_base | awk -v sol=$solvent '{split($0, tmp, "-"); \
        tmp[3] = sol; print sprintf("%s-%s-%s", tmp[1], tmp[2], tmp[3])}')

Вот где лежит "сердце" программы. Мы начнем с использования echo для вывода содержимого old_file_name в STDOUT, а затем с помощью канала (|) для перенаправления echo STDOUT на awk в STDIN. Таким образом, awk будет работать с базовым именем, которое мы получили на предыдущем шаге.

Обратите внимание, что мы используем опцию -v при вызове awk.Мы делаем это для «передачи» внешних переменных в awk, чтобы их можно было использовать при обработке ввода. С помощью -v sol=$solvent мы можем ссылаться на sol внутри awk, и его значение будет значением переменной solvent в скрипте. (т.е. второй параметр, передаваемый при запуске скрипта). Затем мы находим awk "сценарий" между фигурными скобками. Он содержит 3 отдельные инструкции:

a) split($0, tmp, "-"): функция split() примет весь ввод ($0 внутри awk) и разделить его на символы -. Результаты будут возвращены в массиве tmp.

b) tmp[3] = sol: мы просто присвоим sol третьему элементу. Обратите внимание, что awk начинает индексацию с 1, а не с 0! Мы жестко кодируем индекс, потому что знаем формат имени входного файла. В противном случае вам может потребоваться быть осторожным и проверить размер массива вручную.

c) print sprintf("%s-%s-%s", tmp[1], tmp[2], tmp[3]): sprintf() функция «вернет» строку, которую мы получим, назначив переданные значения заполнителям, определенным знаком процента (%). Как и в C, %s — это заполнитель для строки. В этом случае sprintf() вернет три элемента массива tmp, соединенные дефисами (-) в виде строки.Поскольку ранее мы изменили значение tmp[3] на желаемый результат, результат будет таким, каким мы его ожидаем. Затем мы вызываем print для вывода этой строки в STDOUT. Поскольку вся эта команда находится в структуре подстановки команд (например, $()), содержимое, выводимое в STDOUT, будет присвоено переменной new_file.

Тогда у нас есть желаемый результат! Вы можете проверить это, запустив echo $new_file и проверив вывод вашего терминала. Если вы передадите 3-й параметр в командной строке, чтобы контролировать, какой ввод следует изменить в имени файла, вы можете просто передать его в awk через параметр -v и обработать имя так, как вы хотите. внутри самого awk.

Примеры выходных данных

Вот некоторые результаты, которые мы получили на нашей машине:

bash-3.2$ ./foo.sh input1-input2-input3 input-5
input1-input2-input-5
bash-3.2$ ./foo.sh input1-input2-input3 input-4
input1-input2-input-4

Мы назвали наш скрипт foo.sh, у нас плохо с именами :P

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

3
ответ дан 10 November 2020 в 21:39

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

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