Если Ваша поддержка приложений это, можно попробовать передающий порт 0 к приложению. Если Ваше приложение передаст это ядру, то порт будет динамично выделен во время запроса и, как гарантируют, не будет использоваться (выделение перестанет работать, если все порты уже будут использоваться).
Иначе можно сделать это вручную. Сценарий в Вашем ответе имеет состояние состязания, единственный способ избежать, чтобы это атомарно проверило, открыто ли это путем попытки открыть его. Если порт используется, программа должна выйти с отказом открыть порт.
Например, скажите, что Вы пытаетесь послушать с GNU netcat.
#!/bin/bash
read lower_port upper_port < /proc/sys/net/ipv4/ip_local_port_range
while :; do
for (( port = lower_port ; port <= upper_port ; port++ )); do
nc -l -p "$port" 2>/dev/null && break 2
done
done
Вы присваиваетесь files
как скалярная переменная вместо переменной типа массив.
В
files=$HOME/print/*.pdf
Вы присваиваете некоторую строку как /home/highsciguy/print/*.pdf
к $files
скаляр (иначе строка) переменная.
Использование:
files=(~/print/*.pdf)
или
files=("$HOME"/print/*.pdf)
вместо этого. Оболочка развернет это globbing шаблон в список путей к файлам и присвоит каждого из них к элементам $files
массив.
Расширение шарика сделано во время присвоения.
Вы не должны использовать нестандартные sh функции, и Вы могли использовать свою систему sh
вместо bash
здесь путем записи этого:
#!/bin/sh -
[ "$#" -gt 0 ] || set -- ~/print/*.pdf
for file do
ls -d -- "$file"
done
set
должен присвоиться "$@"
массив позиционных параметров.
Другой подход, возможно, был должен сохранить globbing шаблон в скалярной переменной:
files=$HOME/print/*.pdf
И имейте оболочку, разворачивают шарик в то время $files
переменная расширена.
IFS= # disable word splitting
for file in $files; do ...
Здесь, потому что $files
не заключается в кавычки (который Вы не должны обычно делать), его расширение подвергается разделению слова (который мы отключили здесь), и globbing/filename поколение.
Так *.pdf
будет расширен до списка соответствия файлам. Однако, если $HOME
содержавшие подстановочные символы, они могли быть расширены также, который является, почему все еще предпочтительно использовать переменную типа массив.
Вы, возможно, видели вещи как files=$*
и files=~/print/*.pdf
в более старых оболочках без массивов, и затем ls $files
.
Подстановка переменных, которая не является в двойных кавычках, интерпретирует значение переменной как разделенный от пробела список подстановочных шаблонов оболочки, которые заменяются путем соответствия именам файлов, если существует кто-либо. Например, после files=~/print/*.pdf
, ls $files
расширяется до чего-то как ls
с аргументами /home/highsciguy/print/bar.pdf
, /home/highsciguy/print/foo.pdf
, и т.д. В случае files=$*
, это присвоение конкатенирует, аргументы передали сценарию с промежуточными пробелами, и ls $files
разделяет их, отступают.
Все это ломается, если у Вас есть имена файлов, содержащие пробел или globbing символы, который является, почему Вы не должны делать вещей этот путь. Используйте массивы вместо этого.
files=("$@")
if ((${#files[@]} == 0)); then
files=("$HOME"/print/*.pdf)
fi
Отметьте это
var=(…)
."$files"
пусто когда files
массив, чей элемент индекса 0 сброшен или пустая строка. Также [ "X$foo" = "X" ]
устаревший путь состоит в том, чтобы протестировать ли $foo
пусто: вся современная реализация оболочек [ -n "$foo" ]
правильно. В ударе можно использовать [[ -n $foo ]]
.В оболочках, которые не поддерживают массивы, существует на самом деле один массив: позиционные параметры к оболочке или текущей функции. Здесь, Вам действительно не нужно files
массив, на самом деле было бы легче использовать позиционные параметры.
#!/bin/sh
if [ "$#" -eq 0 ]; then
set -- ~/print/*.pdf
fi
for file do …