В питоне можно сделать
from subprocess import *
def main():
for i in range(90, 110):
try :
url = "url/"+str(i)
check_output(["wget", url])
except CalledProcessError:
print "Wget returned none zero output, quiting"
sys.exit(0)
Ознакомьтесь с документацией для подпроцесса, если хотите узнать большеhttps://docs.python.org/2/library/subprocess.html
files=(
file1 file2 "the goose incident.png"
"another file"
file3 file-4 "fifth file" file6
"this is file7 with a
newline in the middle of the name" )
cd ~/dir1 &&
cp "${files[@]}" ~/dir2
Это скопирует имена, упомянутые в списке files
, из ~/dir1
в ~/dir2
.
Новые строки между элементами в списке files
не важны, за исключением новой строки в последнем элементе, который представляет собой имя файла с внедренной в него новой строкой (просто для того, чтобы показать, что вы также можете иметь их, без вопросов ).
Список можно было бы и написать
files=(
file1
file2
"the goose incident.png"
"another file"
file3
file-4
"fifth file"
file6
"this is file7 with a
newline in the middle of the name"
)
или как
files=( file1 file2 "the goose incident.png" "another file" file3 file-4
"fifth file" file6 "this is file7 with a
newline in the middle of the name" )
Как насчет этого:
#!/usr/bin/env bash
files="1
2
3
4
4
5
6
7
8
9 10 11"
IFS=$'\n'
for file in $files
do
touch "$file"
done
Просто замените touch "$file"
тем, что вам нужно. То недостатком этого решения является то, что оно будет разветвлять новый процесс для каждый файл, как вы можете видеть с strace
и, таким образом, будет медленным для большое количество файлов:
$ strace -f./cp-here-doc.sh |& grep 'execve("/usr/bin/touch"'
[pid 17917] execve("/usr/bin/touch", ["touch", "1"], [/* 63 vars */]) = 0
[pid 17918] execve("/usr/bin/touch", ["touch", "2"], [/* 63 vars */]) = 0
[pid 17919] execve("/usr/bin/touch", ["touch", "3"], [/* 63 vars */]) = 0
[pid 17920] execve("/usr/bin/touch", ["touch", "4"], [/* 63 vars */]) = 0
[pid 17921] execve("/usr/bin/touch", ["touch", "4"], [/* 63 vars */]) = 0
[pid 17922] execve("/usr/bin/touch", ["touch", "5"], [/* 63 vars */]) = 0
[pid 17923] execve("/usr/bin/touch", ["touch", "6"], [/* 63 vars */]) = 0
[pid 17924] execve("/usr/bin/touch", ["touch", "7"], [/* 63 vars */]) = 0
[pid 17925] execve("/usr/bin/touch", ["touch", "8"], [/* 63 vars */]) = 0
[pid 17926] execve("/usr/bin/touch", ["touch", "9 10 11"], [/* 63 vars */]) = 0
Вы можете использовать xargs
для запуска touch
или cp
только в окончательном сценарии. один раз и заставить скрипт работать быстрее:
#!/usr/bin/env bash
files="1
2
3
4
4
5
6
7
8
9 10 11"
echo "$files" | tr '\n' '\0' | xargs -0 touch
Результат:
$ strace -f./cp-here-doc.sh |& grep 'execve("/usr/bin/touch"'
[pid 18290] execve("/usr/bin/touch", ["touch", "1", "2", "3", "4", "4", "5", "6", "7", "8", "9 10 11"], [/* 63 vars */]) = 0
Также обратите внимание, что в Linux по крайней мере имена файлов могут содержать новые строки, поэтому вам нужно выбрать другой разделитель, если хотя бы одно из ваших имен файлов содержит новую строку.
ОП спросил:
what does IFS=$'\n' mean
Это буквально означает новую строку. Вы можете прочитать об этомman bash
:
Words of the form $'string' are treated specially. The word
expands to string, with backslash-escaped char- acters replaced
as specified by the ANSI C standard. Backslash escape
sequences, if present, are decoded as follows:
\a alert (bell)
\b backspace
\e
\E an escape character
\f form feed
\n new line
Ваш окончательный сценарий может выглядеть так:
#!/usr/bin/env bash
files="1
2
3
4
5
6
7
8
9 10 11"
echo "$files" | tr '\n' '\0' | xargs -0 cp -t {} dir
Я бы выбрал вариант xargs
, так как он намного быстрее и безопаснее -см. комментарий Кусалананды ниже. я не бежал тесты с помощью команды cp
, но когда я протестировал touch
для создания файлов в список $(seq 1 1000000)
потребовалось всего 16 секунд для xargs
это, но для версии с циклом for потребовалось целых 42 минуты. Также, к моему удивлению xargs
смог разбить список аргументов на несколько команды, так что Argument list too long
не будет проблемой.