Здесь у вас две проблемы. Во-первых, ваш исходный путь вряд ли будет правильным. Если имя файла на самом деле не начинается с точки, похоже, что вы пытаетесь указать текущий каталог, но не включаете косую черту между точкой и именем файла.
Ваша вторая проблема в основном аналогична: когда вы говорите «steph», вы говорите копии создать файл с именем «steph». Если вы хотите, чтобы существующий каталог с именем «steph» был вашей целью, он должен заканчиваться косой чертой.
cp ArtTunnel.jpg../steph/
Обратите внимание, что «./» не требуется перед именем файла ArtTunnel.jpg, когда вы выполняете эту команду из того же каталога, в котором в данный момент находится файл.
В некоторых версиях Bash есть ошибка, из-за которой они не ожидают должным образом процессы, порожденные подстановкой процессов.
Вызов dump
в замене процесса выполняется как асинхронный процесс. Это означает, что tee
записывает в него свои выходные данные, после чего конвейер завершает работу. Конвейер завершает работу, потому что вывод из tee
буферизуется; если вы запишете больше данных, чем размер конвейерного буфера , tee
придется ждать, пока dump
не воспользуется ими, и ваш исходный код, вполне возможно, будет работать.
Предполагая, что вы записываете только небольшой объем данных, как вы делаете в вопросе, вы затем читаете из a.txt
сразу после завершения конвейера, до того, как dump
сможет записать что-либо в файл (он все еще спит в фоновом режиме, а данные висят в конвейерном буфере ).
Если вы посмотрите на файл a.txt
после запуска ошибочного кода, вы заметите, что он содержит строку twice
.Таким образом, в конце концов, после небольшой задержки, обеспечиваемой sleep 1
в функции, он туда попадает.
Чтобы предотвратить преждевременное завершение конвейера, добавьте cat
в конце:
dump() {
(sleep 1; cat) > "$1"
}
(sleep 0; echo "twice") | tee >(dump "./a.txt") | cat
echo "$(< "a.txt")"
Это заставляет его работать, потому что теперь процесс cat
должен ждать, пока выходные данные dump
поступят по каналу (их не будет, но он не знает, что ). Это задерживает завершение конвейера до возврата вызова dump
. В этот момент данные уже были записаны в a.txt
и могут быть получены последней командой сценария.
Единственное, что синхронизирует процессы в конвейере, — это ввод-вывод, то есть чтение данных из предыдущего процесса и запись в следующий. Если в какой-то момент процесс ожидает чтения с предыдущего шага, он будет заблокирован до тех пор, пока что-то не будет доступно для чтения или пока предыдущий шаг не закроет свой конец канала.
cat
по умолчанию читает со стандартного ввода. Стандартный вход добавленного cat
связан со стандартным выходом tee
и с заменой процесса на dump
на предыдущем шаге конвейера. Утилита cat
будет читать до тех пор, пока больше нечего читать. Этого не произойдет, пока оба tee
и dump
не завершат выполнение.
Подчищенная версия кода:
dump() {
sleep 1
cat >"$1"
}
echo twice | tee >(dump./a.txt) | cat
cat a.txt