В Linux Mint 19 (Ubuntu 18.04 )просто установите vdpau -драйвер -все решит эту проблему.
Failed to open VDPAU backend libvdpau_radeonsi.so: cannot open shared object file: No such file or directory
Решение:
$ apt install vdpau-driver-all
Оптимизация заключалась бы в использовании {} +
вместо {} \;
.
find. -type f -exec sed -i '1s|^#!/bin/bash|#!/bin/sh|' {} +
Вместо вызова одного процесса sed для каждого найденного файла вы предоставляете файлы в качестве аргументов одному процессу sed.
Спецификация POSIX find на{} +
(жирным шрифтом):
If the primary expression is punctuated by a <plus-sign>, the primary shall always evaluate as true, and the pathnames for which the primary is evaluated shall be aggregated into sets. The utility utility_name shall be invoked once for each set of aggregated pathnames.
Да, sed -i
читает и перезаписывает файл полностью, а так как длина строки меняется, то приходится, так как перемещает позиции всех остальных строк.
...но в этом случае длину строки менять не нужно. Вместо этого мы можем заменить строку hashbang на #!/bin/sh␣␣
с двумя пробелами в конце. ОС удалит их при разборе строки hashbang. (В качестве альтернативы можно использовать два символа новой строки или символ новой строки + решётка, оба из которых создают дополнительные строки, которые оболочка в конечном итоге проигнорирует.)
Все, что нам нужно сделать, это открыть файл для записи с самого начала, не усекая его. Обычные перенаправления >
и >>
не могут этого сделать, но в Bash, кажется, работает перенаправление чтения -записи <>
:
echo '#!/bin/sh ' 1<> foo.sh
или используяdd
(это должны быть стандартные параметры POSIX):
echo '#!/bin/sh ' | dd of=foo.sh conv=notrunc
Обратите внимание, что, строго говоря, оба они также переписывают новую строку в конце строки, но это не имеет значения.
Конечно, приведенное выше безоговорочно перезаписывает начало данного файла. Добавление проверки того, что исходный файл имеет правильный хеш-банг, оставлено в качестве упражнения... Тем не менее, я, вероятно, не стал бы делать это в рабочей среде, и, очевидно, это не сработает, если вам нужно изменить строку на более длинный один.
Файлы представляют собой один длинный непрерывный диапазон байтов. Ваша замена bash
на sh
по существу потребует удаления двух байтов (при условии UTF -8 или аналогичного ), которые составляют ba
. В файлах не может быть дырок, поэтому все, что начинается с sh
, придется записывать в файл на два байта раньше.
Это требует перезаписи всего файла или, по крайней мере, начиная с измененной части.
Существуют способы замены байтов в файле, например, невинными пробелами, если формат позволяет это без перезаписи всего файла, см. принятый ответ.
Гипотетически, если вам нужно внести такое изменение в огромный файл, sed -i
фактически создаст временный файл того же размера, что может быть проблемой.
Эту проблему можно решить с помощью некоторых хитростей, используя такой инструмент, как dd
(, или используя mmap()
или fseek()
в C )для изменения фрагментов в файле по одному. Например, если вы хотите добавить 2 символа в начало файла, вы можете работать в обратном направлении с конца, сдвигая все вперед на 2 символа.
Урок здесь в том, что в UNIX файлы часто обрабатываются как "потоки", проходящие через программу, но их также можно рассматривать как байтовые массивы, которые можно редактировать -на месте.
Я бы сделал:
#! /bin/zsh -
LC_ALL=C # work with bytes instead of characters.
shebang_to_replace=$'#!/bin/bash\n'
new_shebang=$'#!/bin/sh -\n'
length=$#shebang_to_replace
ret=0
for file in **/*(N.L+$((length - 1)));do
if
read -u0 -k $length shebang < $file &&
[[ $shebang = $shebang_to_replace ]]
then
print -rn -- $new_shebang 1<> $file || ret=$?
fi
done
exit $ret
Подобно подходу @ilkkachu , файл перезаписывается строкой точно такого же размера. Различия:
.git
один например )так как маловероятно, что вы захотите учитывать те (которые вы использовали find./*
которые пропустили бы скрытые файлы и каталоги текущего каталога, но не подкаталогов ). Добавьте квалификатор D
glob, если они вам нужны. .
как эквивалент -type f
, поэтому мы уже извлекаем информацию об индексе из файл, так что мы могли бы также проверить размер там ). zsh
так как другие оболочки не могут работать с произвольными значениями байтов ). #!/bin/sh -
в качестве замены, которая является правильным шебангом для /bin/sh
скриптов(#!/bin/bash -
кстати, будет правильным шебангом для /bin/bash
скриптов ). См. Почему " -" в " #! /bin/sh -" шебанге? для получения подробной информации. В статусе выхода сообщается об ошибках перезаписи файлов, но не об ошибках обхода дерева каталогов и не об ошибках чтения файлов, хотя это можно было бы добавить.
В любом случае, он заменяет только шебанги, которые точно #!/bin/bash
, а не другие шебанги, которые используют bash
в качестве интерпретатора, например #! /bin/bash
, #! /bin/bash -Oextglob
, #! /usr/bin/env bash
, #! /bin/bash -efu
. Для них вам нужно решить, что делать. -efu
— это опции sh
, но -Oextglob
не имеет, например, эквивалента sh
.
Вы можете расширить его для поддержки самых простых случаев, таких как:
#! /bin/zsh -
LC_ALL=C # work with bytes instead of characters.
zmodload zsh/system || exit
minlength=11 # length of "#!/bin/bash"
maxlength=1024 # arbitrary here.
ret=0
for file in **/*(N.L+$minlength);do
if
sysread -s $maxlength buf < $file &&
[[ $buf =~ $'(^#![\t ]*((/usr)?/bin/env[ \t]+bash|/bin/bash)([ \t]+-([aCefux]*))?[ \t]*)\n' ]]
then
shebang=$match[1] newshebang="#!/bin/sh -$match[5]"
print -r -- ${(r[$#shebang])newshebang} 1<> $file || ret=$?
fi
done
exit $ret
Здесь разрешен ряд различных шебангов с рядом поддерживаемых опций, которые воспроизводятся в новом /bin/sh
шебанге, дополненном справа -(с флагом расширения параметра r[length]
)до того же размера. как оригинал.