Как я могу "тройник" переменное число раз в bash "для цикла"?

Я понимаю, что могу:

ssh archive_server -l user -n "cat text.csv"|tee -a text1.csv|tee -a text2.csv|tee....|tee -a text10.csv

Есть ли способ сделать это в виде петли?

for i in `seq 1 10`; do
  echo $i
  tee ???
done

2 ответа

Решение

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

cat text.csv | tee -a text{1..10}.csv

Если количество файлов является динамическим, вы можете использовать цикл в $() вставить имена файлов в командную строку:

cat text.csv | tee -a $(
    for i in $(seq 1 $filecount); do
        echo text$i;
    done)

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

Предполагая, что ваша оболочка действительно bash (не /bin/sh), вы можете построить массив (и использовать стиль C for цикл, который в отличие от нестандартной внешней команды seq, гарантированно будет доступен везде, где есть bash):

#!/bin/bash
filenames=( )
for ((i=1; i<=10; i++)); do    # note that the "10" here can be a variable name
  filenames+=( "file$i.txt" )
done
tee -a -- "${filenames[@]}" <text.csv

Если вам нужна совместимость с /bin/sh, это становится немного более многословным:

#!/bin/sh
tee_between() (
  prefix=$1; suffix=$2; start=$3; end=$4
  set --
  i=$(( $start - 1 )); while [ $(( ( i += 1 ) <= end )) -ne 0 ]; do
    set -- "$@" "file$i.txt"
  done
  exec tee -a -- "$@"
)

tee_between "file" ".txt" 1 10 <text.csv

Замечания:

  • set -- изменяет список аргументов текущего процесса (или, в данном случае, текущей функции), используя его в качестве массива, который мы можем динамически изменять.
  • tee_between() ( ) вместо tee_between() { } означает, что функция выполняется в подоболочке - это совершенно отдельный раздвоенный процесс. В результате этого выбора exec Команда заменит только эту подоболочку с копией tee а не родительский процесс.
Другие вопросы по тегам