Создание каталогов в цикле и движущихся файлах к тем каталогам

По-видимому, заголовок и тело вопроса не казались вполне тем же мне. Вот два решения:

Импорт данных из внешнего файла в сценарий 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

3
13.03.2015, 01:27
4 ответа
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
3
27.01.2020, 21:11
#!/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

Полезные ссылки:

2
27.01.2020, 21:11

С помощью этой программы 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
1
27.01.2020, 21:11
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 выполняет двойную функцию и здесь: он также служит счетчиком - параметр оболочки $ # всегда сообщает нам, сколько элементов у нас уже сложено в стек.

Но ... Вот пошаговая инструкция:

  1. d = 0; set ./somedirname
    • $ d var будет увеличиваться на единицу для каждого нового созданного каталога. Здесь он инициализируется нулем.
    • ./ somedirname - это то, что вам нравится. Тем не менее, префикс ./ важен - он не только обязательно устанавливает корень всех операций в текущий каталог, он также позволяет вам указать любое имя, которое вы хотите (если вы хотите сходить с ума и используйте символы новой строки или начинайте с дефиса, вы можете смело - но это, вероятно, не рекомендуется) . Поскольку имя аргумента всегда начинается с ./ , никакая команда никогда не будет неправильно интерпретировать его как параметр в командной строке.
  2. для f в ./*
    • Это запускает цикл по всем (если есть) совпадений для * в текущем каталоге. Опять же, каждое совпадение имеет префикс ./ .
  3. [-f "$ f"]
    • проверяет, что соответствие каждой итерации определенно является обычным файлом ( или ссылка на один) и ...
  4. set "$ f" "$ @"
    • размещает совпадения одно перед другим в массиве оболочки. Таким образом, ./ somedirname всегда находится в конце массива.
  5. ["$ d" -lt "$ ((d + = $ #> 5))"]
    • добавляет От 1 до $ d , если в «$ @» более 5 элементов массива, при одновременной проверке результата на приращение.
  6. || continue
    • Если одна из команд [-f "$ f"] set ... ["$ d" -lt ... не возвращает true цикл переходит к следующей итерации и не пытается завершить оставшуюся часть цикла. Это одновременно эффективно и безопасно.
  7. mkdir "$ 6 $ d"
    • Поскольку предложение continue гарантирует, что мы сможем добраться до этой точки, только если $ #> 5 наш ./ somedirname теперь находится в $ 6 , а значение $ d было просто увеличено на единицу. Таким образом, для первой группы из 5 сопоставленных и перемещенных файлов создается каталог с именем ./ somedirname1 , а для пятого ./ somedirname5 и так далее. Важно отметить, что эта команда завершается ошибкой , если какое-либо имя пути с целевым именем пути уже существует. Другими словами, эта команда только успешна, если определенно уже не существует существующего каталога с таким же именем.
  8. mv "$ @ $ d"

    • Это расширяет массив, добавляя значение для $ d в конец последнего элемента, который является именем целевого каталога. Таким образом, он расширяется как:

    mv ./file5 ./file4 ./file3 ./file2 ./file1 ./somedirname1

    • ... что именно то, что вы хотите.
  9. || ! break

    • Если одна из двух предыдущих команд не завершилась успешно по какой-либо причине, for loop break s. ! отправляет логическое значение, обратное возврату break , которое обычно равно нулю, поэтому break возвращает 1.Таким образом, цикл вернет false, если в любой из предыдущих команд произойдет какая-либо ошибка. Это важно - для циклов - в отличие от циклов while / until - не подразумевают тестов, а только итерацию. Без явного тестирования возврата этих двух команд оболочка не обязательно остановится из-за ошибки - и set -e , скорее всего, полностью уничтожит родительскую оболочку. Скорее это гарантирует значимый возврат и то, что цикл не будет продолжать повторяться, если что-то пойдет не так.

    • На первый взгляд может показаться, что это единственный ответ, который остановится, например, если mkdir ./somedirname не вернет true - все остальные будут продолжать цикл ( и, вероятно, повторит ошибку или, что еще хуже, переместит файлы из текущего каталога в существующий каталог и, возможно, поверх других файлов с таким же именем) . Работая с произвольными именами файлов в циклах, вы должны всегда проверять наличие исходного файла и на предмет существования цели.

  10. shift 5
    • Этот сдвиг смещает первые 5 элементов в массиве arg оболочки - который помещает ./ somedirname обратно в $ 1 и сбрасывает состояние массива для следующей итерации.
2
27.01.2020, 21:11

Теги

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