По-видимому, заголовок и тело вопроса не казались вполне тем же мне. Вот два решения:
Импорт данных из внешнего файла в сценарий Bash:
Считайте файл и сохраните его содержание как записи в массиве. (Отметьте: это выполнимо, учитывая содержание Вашего текстового файла. Если бы, для, например, какая-либо строка в файле имела несколько слов без цитат, то массив так сформированный не был бы так желаем.)
declare -a symbols=($(cat input_file.txt | tr '\n' ' '))
Теперь, выполните итерации по объектам массива symbols
следующим образом.
LOG_FILE=/home/user/Desktop/stockquote.txt
for symbol in ${symbols[@]}
do
# echo "Processing $symbol ..."
sh stock "$symbol" >> "$LOG_FILE"
done
На самом деле можно встроить это в сценарий, названный самим запасом. Просто изменитесь sh stock "$symbol"
выше к чему-то вроде этого:
f_process "$symbol" >> "$LOG_FILE"
где f_process
возможно функция, обрабатывающая символ. Если Вы не хотите писать функцию, просто поместите соответствующие строки кода там.
Передающие данные из внешнего файла как аргументы сценарию оболочки:
Связанное решение было уже отправлено neowulf33. Просто воспроизвожу это с исправлениями:
LOG_FILE=/home/user/Desktop/stockquote.txt
while read symbol
do
stock "$symbol" >> "$LOG_FILE"
done < input_file.txt
list=(*) # an array containing all the current file and subdir names
nd=5 # number of new directories to create
((nf = (${#list[@]} / nd) + 1)) # number of files to move to each dir
# add 1 to deal with shell's integer arithmetic
# brace expansion doesn't work with variables due to order of expansions
echo mkdir $(printf "direc%d " $(seq $nd))
# move the files in chunks
# this is an exercise in arithmetic to get the right indices into the array
for (( i=1; i<=nd; i++ )); do
echo mv "${list[@]:(i-1)*nf:nf}" "direc$i"
done
удалите две "эхо-команды" после того, как вы это проверили.
Или, если вы хотите использовать фиксированное количество файлов на каталог, это проще:
list=(*)
nf=10
for ((d=1, i=0; i < ${#list[@]}; d++, i+=nf)); do
echo mkdir "direc$d"
echo mv "${list[@]:i:nf}" "direc$d"
done
#!/bin/sh
d=1 # index of the directory
f=0 # number of files already copied into direc$d
for x in *; do # iterate over the files in the current directory
# Create the target directory if this is the first file to be copied there
if [ $f -eq 0 ]; then mkdir "direc$d"; fi
# Move the file
mv -- "$x" "direc$d"
f=$((f+1))
# If we've moved 5 files, go on to the next directory
if [ $f -eq 5 ]; then
f=0 d=$((d+1))
fi
done
Полезные ссылки:
$ (((...))
[...]
-
в MV - «$ X» ...
С помощью этой программы awk вы можете создавать команды оболочки и, в случае сомнений, заранее проверять, верны ли они ...
awk -v n=5 '{ printf "mv \"%s\" %s\n", $0, "direc" int((NR-1)/n)+1 }' list
Если вас устраивает выходной конвейер, всю команду в sh
. Кроме того, если вы хотите избежать «списка» дополнительных файлов, вы можете создать его «на лету»; тогда вся программа будет ...
ls | awk -v n=5 '{ printf "mv \"%s\" %s\n", $0, "direc" int((NR-1)/n)+1 }' | sh
Вы можете определить другие значения, кроме 5, если вы измените настройку n = 5.
Если вы также хотите создавать целевые каталоги на лету, вот вариант ...
ls | awk -v n=5 '
NR%n==1 { ++c ; dir="direc"c ; print "mkdir "dir }
{ printf "mv \"%s\" %s\n", $0, dir }
' | sh
d=0; set ./somedirname #init dir counter; name
for f in ./* #glob current dir
do [ -f "$f" ] && set "$f" "$@" && #if "$f" is file and...
[ "$d" -lt "$((d+=$#>5))" ] || continue #d<(d+($#>5)) or continue
mkdir "$6$d" && mv "$@$d" || ! break #mk tgtdir and mv 5 files or
shift 5 #break with error
done
Вышеупомянутая команда использует возможность массива arg оболочки связывать строки с заголовком и концом. Например, если вы написали функцию:
fn(){ printf '<%s>\n' "42$@"; }
... и назвали ее так:
fn show me
... она напечатала бы:
<42show>
<me>
...потому что вы можете добавить или добавить к первому или последнему элементу (соответственно) в массиве arg, просто заключив его кавычки вокруг вашей предварительно / прикрепленной строки.
Массив arg выполняет двойную функцию и здесь: он также служит счетчиком - параметр оболочки $ #
всегда сообщает нам, сколько элементов у нас уже сложено в стек.
Но ... Вот пошаговая инструкция:
d = 0; set ./somedirname
$ d
var будет увеличиваться на единицу для каждого нового созданного каталога. Здесь он инициализируется нулем. ./ somedirname
- это то, что вам нравится. Тем не менее, префикс ./
важен - он не только обязательно устанавливает корень всех операций в текущий каталог, он также позволяет вам указать любое имя, которое вы хотите (если вы хотите сходить с ума и используйте символы новой строки или начинайте с дефиса, вы можете смело - но это, вероятно, не рекомендуется) . Поскольку имя аргумента всегда начинается с ./
, никакая команда никогда не будет неправильно интерпретировать его как параметр в командной строке. для f в ./*
*
в текущем каталоге. Опять же, каждое совпадение имеет префикс ./
. [-f "$ f"]
set "$ f" "$ @"
./ somedirname
всегда находится в конце массива. ["$ d" -lt "$ ((d + = $ #> 5))"]
$ d
, если в «$ @»
более 5 элементов массива, при одновременной проверке результата на приращение. || continue
[-f "$ f"]
set ...
["$ d" -lt ...
не возвращает true цикл переходит к следующей итерации и не пытается завершить оставшуюся часть цикла. Это одновременно эффективно и безопасно. mkdir "$ 6 $ d"
continue
гарантирует, что мы сможем добраться до этой точки, только если $ #> 5
наш ./ somedirname
теперь находится в $ 6
, а значение $ d
было просто увеличено на единицу. Таким образом, для первой группы из 5 сопоставленных и перемещенных файлов создается каталог с именем ./ somedirname1
, а для пятого ./ somedirname5
и так далее. Важно отметить, что эта команда завершается ошибкой , если какое-либо имя пути с целевым именем пути уже существует. Другими словами, эта команда только успешна, если определенно уже не существует существующего каталога с таким же именем. mv "$ @ $ d"
$ d
в конец последнего элемента, который является именем целевого каталога. Таким образом, он расширяется как: mv ./file5 ./file4 ./file3 ./file2 ./file1 ./somedirname1
|| ! break
Если одна из двух предыдущих команд не завершилась успешно по какой-либо причине, for
loop break
s. !
отправляет логическое значение, обратное возврату break
, которое обычно равно нулю, поэтому break
возвращает 1.Таким образом, цикл вернет false, если в любой из предыдущих команд произойдет какая-либо ошибка. Это важно - для
циклов - в отличие от циклов while / until
- не подразумевают тестов, а только итерацию. Без явного тестирования возврата этих двух команд оболочка не обязательно остановится из-за ошибки - и set -e
, скорее всего, полностью уничтожит родительскую оболочку. Скорее это гарантирует значимый возврат и то, что цикл не будет продолжать повторяться, если что-то пойдет не так.
На первый взгляд может показаться, что это единственный ответ, который остановится, например, если mkdir ./somedirname
не вернет true - все остальные будут продолжать цикл ( и, вероятно, повторит ошибку или, что еще хуже, переместит файлы из текущего каталога в существующий каталог и, возможно, поверх других файлов с таким же именем) . Работая с произвольными именами файлов в циклах, вы должны всегда проверять наличие исходного файла и на предмет существования цели.
shift 5
сдвиг
смещает первые 5 элементов в массиве arg оболочки - который помещает ./ somedirname
обратно в $ 1
и сбрасывает состояние массива для следующей итерации.