Вот несколько команд для копирования каталогов с информацией о ходе выполнения.
Если есть много маленьких файлов:
cp -av sourcedir targetdir | pv -l -s filecount > logfile
Это сообщит о прогрессе, основанном на количестве копируемых файлов.
Вы можете перенаправить на /dev/null
, если вам не нужен logfile
.
Используйте следующую команду для получения filecount
:
find sourcedir | wc -l
Если есть несколько огромных файлов:
tar c sourcedir | pv -s size | tar x -C targetdir
Это сообщит о прогрессе на основе байтов, которые копируются.
targetdir
должен существовать.
Используйте следующую команду для получения size
:
du -sh sourcedir
Если вы хотите использовать rsync:
rsync -ai sourcedir/ targetdir/ | pv -l -s filecount > logfile
Получите filecount
, как показано выше.
Если вы копируете в одной системе, то rsync -a
практически то же самое, что cp -a
. Преимущества rsync - при копировании по сети или при обновлении (или сравнении) предыдущей копии.
См. подробнее здесь:
Bash 4.3 и более поздние версииподдерживают «ссылки на имена» или namerefs (аналогичная концепция существует в ksh93
, но область видимости раздражает different):
#!/bin/bash
array1=('array1string1' 'array1string2')
array2=('array2string1' 'array2string2')
array_names=('array1' 'array2')
for a in "${array_names[@]}"; do
declare -n arr="$a"
for b in "${arr[@]}"; do
echo "$b"
done
done
Переменная arr
является ссылкой на имя, которая действует как псевдоним для именованной переменной (в данном примере это переменная с именем $a
).
Без ссылок namerefs в более ранних версиях Bash одним из решений было бы создание нового массива, содержащего все элементы из других массивов:
all=( "${array1[@]}" "${array2[@]}" )
... немного похоже на массив array_names
в вопрос, но с содержимым всех массивов, а затем перебрать "${all[@]}"
.
Также можно использовать eval
, но полученный код выглядит поразительно ужасно.
См. ответ glenn jackman для варианта с переменной косвенностью (представленный в его текущей форме с Bash версии 2).
У @Kusalananda есть лучший ответ для последних версий bash. Для более ранних версий вы можете использовать косвенную переменную:
for a in ${array_names[@]}; do
tmp="${a}[@]"
for b in "${!tmp}"; do echo "$b"; done # or: printf "%s\n" "${!tmp}"
done
См. 4-й абзацhttps://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion
В качестве вариации сказанного:
#!/bin/bash
array1=('array1 string1' 'array1 string2')
array2=('array2 string1' 'array2 string2')
array_names=('array1' 'array2')
for (( i=0; i<${#array_names[@]}; i++ )); do
declare -n arr="${array_names[i]}"
for (( j=0; j<${#arr[@]}; j++ )); do
echo "${arr[j]}"
done
done
Доступ к элементам по индексу вместо этого