У меня есть несколько файлов (таблицы), названные как: институт_
модель_
сценарий_
река.txt
(институт, модель, сценарий и река являются переменными.) Я хотел бы создать a for
цикл, который определит каждого файлы, которые имеют то же название института и в то же время то же название сценария, для добавления результатов каждой различной модели в том же выходном файле, с помощью следующей команды:
paste filename1.txt filename2.txt > output_file.txt
Я знаю, как создать a for
цикл по другой папке, но не по именам файлов. У кого-либо есть идея?
Как минимальный пример, имена файлов могли быть следующие:
wbm_gfdl_rcp8p5_mississippi.txt
wbm_hadgem_rcp8p5_mississippi.txt
matsiro_gfdl_rcp8p5_mississippi.txt
matsiro_ipsl_rcp4p5_mississippi.txt
matsiro_hadgem_rcp4p5_mississippi.txt
matsiro_miroc_rcp8p5_mississippi.txt
Затем я хотел бы добавить следующие файлы вместе:
wbm_gfdl_rcp8p5_mississippi.txt with
wbm_hadgem_rcp8p5_mississippi.txt
matsiro_ipsl_rcp4p5_mississippi.txt with
matsiro_hadgem_rcp4p5_mississippi.txt
matsiro_gfdl_rcp8p5_mississippi.txt with
matsiro_miroc_rcp8p5_mississippi.txt
Если файлы - все в том же dir, Вы можете:
ls |
awk -F_ '{ i=$1; m=$2; s=$3; f[i"_"s] = f[i"_"s] " " $0 }
END{ for(insc in f)
printf "paste%s >out_%s.txt\n",f[insc],insc
}'
который разделяет имя файла на "_" (-F_
), устанавливает переменные i, m, s к первым 3 частям имени файла (институт, модель, сценарий), и накапливает в массиве f имя файла. Массив индексируется только институтом и сценарием, таким образом, все модели связываются (m, не используется). Заключительный КОНЕЦ печатает массив f и использует индекс (institute_scenario) в качестве названия выходного файла. С Вашими примерами это производит
paste wbm_gfdl_rcp8p5_mississippi.txt wbm_hadgem_rcp8p5_mississippi.txt >out_wbm_rcp8p5.txt
paste matsiro_hadgem_rcp4p5_mississippi.txt matsiro_ipsl_rcp4p5_mississippi.txt >out_matsiro_rcp4p5.txt
paste matsiro_gfdl_rcp8p5_mississippi.txt matsiro_miroc_rcp8p5_mississippi.txt >out_matsiro_rcp8p5.txt
Затем необходимо передать это по каналу в оболочку, чтобы выполнить его. Добавить | sh
к последней строке выше, чтобы сделать это.
Для удаления некоторых столбцов из входных файлов необходимо изменить awk строку, которая собирает все входные имена файлов. В 1-й awk строке:
{ i=$1; m=$2; s=$3; f[i"_"s] = f[i"_"s] " " $0 }
имя файла составляет "0$". Например, если Вы изменяете эту строку в:
{ i=$1; m=$2; s=$3; f[i"_"s] = f[i"_"s] sprintf(" <(cut -f4 %s)",$0) }
затем Вы произведете пример:
paste <(cut -f4 wbm_gfdl_rcp8p5_mississippi.txt) <(cut -f4 wbm_hadgem_rcp8p5_mississippi.txt) >out_wbm_rcp8p5.txt
но если Вы хотите сократить только 2-е имя файла, это немного более сложно, и Вам нужно это вместо этого:
{ i=$1; m=$2; s=$3;
if(f[i"_"s]=="")add = $0; else add = sprintf("<(cut -f4 %s)",$0);
f[i"_"s] = f[i"_"s] " " add }
таким образом, Вы доберетесь
paste wbm_gfdl_rcp8p5_mississippi.txt <(cut -f4 wbm_hadgem_rcp8p5_mississippi.txt) >out_wbm_rcp8p5.txt
Если sh
не понимает синтаксис <(cut ...)
затем замените его bash
.
В первую очередь, нет никакого различия между for
петля для справочников и один для файлов. Это - точно то же самое. Помните, что на *отклоняют, все - файл .
Так, Ваша петля была бы чем-то вроде этого:
for institute in institute1 institute2 institute3
do
for scenario in scenario1 scenario2 scenario3
do
paste "$institute"_*_"$scenario"* > "$institute"_"$scenario".out
done
done
, Если Вы не знаете институт и названия сценария, Вы могли бы просто управлять этим для всех файлов и извлечь их из имен файлов (как долго, поскольку Ваши имена не содержат пробел):
for f in *; do echo "${f/_*} ${f##*_}"; done |
sort -u | while read ins sce; do
paste "$ins"_*_"$sce"* > "$ins"_"$sce".out
done
Возможно, использование ls команда. Что-то как ls $institute_*_$scenario_*.txt
должно возвратить все файлы с тем же институтом и сценарий.