Скорее всего, это произошло из-за того, что вы использовали два разных менеджера пакетов(dpkg
или его внешний интерфейс apt-get
и сам pip
)с одним и тем же префиксом(/usr
). Я предполагаю, что либо
apt-get upgrade
обновление некоторых зависимостей, но некоторые другие файлы, которые были установлены pip
, не обновились, потому что dpkg
и apt-get
просто не знали о них ИЛИ apt-get remove
, и поскольку apt-get
ничего не знал об использовании этого пакета (, так как другой пакет был установлен pip
и, следовательно, не в базе данных dpkg
), он не предупредил вас о взломе других пакетов. Не зная, какие пакеты были установлены с каким менеджером пакетов, я не могу дать вам конкретных советов по восстановлению вашей системы, только общие советы:
Не используйте несколько разных менеджеров пакетов.Всегда используйте только один менеджер пакетов для данного (поддерева -)вашей файловой системы, иначе вы получите несоответствия и/или конфликты. Менеджер пакетов Debian для дерева /usr
называется dpkg
, и без его вызова никто не должен никогда касаться /usr
.
Конечно, не помогает то, что большинство связанных с python -людей, с которыми вы столкнетесь, попытаются протолкнуть pip, даже говоря вам sudo pip install
; не надо. По какой-то причине существуют дистрибутивы, содержащие материалы для Python. Также см. этот связанный вопрос на AskUbuntu и этот ответ на StackOverflow .
Вы можете попытаться устранить беспорядок, установив свежий пункт с помощью
apt-get purge python-pip python3-pip
apt-get install python-pip python3-pip
однако могут быть оставлены файлы, которые могут мешать работе, о которых dpkg
не знает, поскольку они были установлены pip
. Надежным -огневым способом будет проверка всех файлов в /usr/lib/python*
на предмет их принадлежности к пакету debian, и если нет, то удаление их без исключения.
Опять же, только используют dpkg
и его интерфейсные инструменты, такие как apt-get
, aptitude
, synaptic
,... для модификации /usr
. Если вам нужно установить что-либо общесистемное -, чего нет в виде пакета .deb
, либо создайте пакет и установите его с dpkg
, либо установите его с /usr/local
.
Использование GNUsed
:
sed -s -e $'$a\\\n'./*.txt >concat.out
Это объединяет все данные в concat.out
и в то же время добавляет пустую строку в конец каждого обрабатываемого файла.
Опция -s
для GNU sed
заставляет адрес $
соответствовать последней строке в каждого файла вместо, как обычно, последней строки всех данных. Команда a
добавляет одну или несколько строк в указанное место, а добавляемые данные являются новой строкой. Новая строка кодируется как $'\n'
, то есть как «строка C -», что означает, что мы используем оболочку, которая понимает эти (как bash
илиzsh
). В противном случае это должно было бы быть добавлено как буквальная новая строка:
sed -s -e '$a\
'./*.txt >concat.out
На самом деле, '$a\\'
и '$a\ '
, кажется, тоже работают, но я не совсем уверен, почему.
Это также работает, если кто-то считает, что команда a
слишком утомительна, чтобы ее правильно выполнить:
sed -s -e '${p;g;}'./*.txt >concat.out
Любая из этих вариаций также будет вставлять пустую строку в конец вывода последнего файла. Если эта последняя новая строка не нужна, удалите ее, передав общий результат через sed '$d'
перед перенаправлением в выходной файл :
sed -s -e '${p;g;}'./*.txt | sed -e '$d' >concat.out
Пример использования Perl.
$ perl -e 'while(<>){print}continue{print"\n" if eof}' *.txt > concat.txt
, который можно упростить до
$ perl -ne 'print; print "\n" if eof' [abc].txt > concat.txt
Не одна команда, а простой -лайнер:
for f in *.txt; do cat -- "$f"; printf "\n"; done > newfile.txt
Это выдаст эту ошибку:
cat: newfile.txt: input file is output file
Но вы можете игнорировать это, по крайней мере, в системах GNU/Linux. Стефан Шазеля указал в комментариях, что, по-видимому, в других системах это может привести к бесконечному циклу, поэтому, чтобы избежать этого,попробуй:
for f in *.txt; do
[[ "$f" = newfile.txt ]] || { cat -- "$f"; printf "\n"; }
done > newfile.txt
Или просто не добавляйте расширение .txt
к выходному файлу (оно не нужно и вообще не имеет никакого значения )так что оно не будет включено в петля:
for f in *.txt; do cat -- "$f"; printf "\n"; done > newfile
Использование GNUawk
:
gawk -v RS='^$' -v ORS= '{
print sep $0; sep="\n";
}'./file*.txt >single.file
префиксная точка -косая черта в имени файла ./
используется, чтобы избежать проблем с файлами с именами, подобными file=x.txt
, например, поскольку awk
читает такие строки как переменная , если они идут после кодов awk
;
Другим подходом GNU awk
может быть:
gawk 'BEGINFILE{if (ARGIND>1) print ""};1'./file*.txt >single.txt
что лучше, поскольку добавляет пустую строку, даже если последняя строка не заканчивается символом новой строки, и позволяет избежать загрузки всех файлов в память.
существует также sed
альтернатива, но чтобы удалить самую последнюю \n
ewline, вы должны добавить еще одну вертикальную черту sed... |
, чтобы удалить ее.
sed -s '$s/$/\n/' file*.txt >single.file
zsh
имеет квалификатор P
glob для префикса каждого имени файла, полученного из glob с произвольным аргументом.
Хотя он обычно используется для таких вещей, как cmd *.txt(P[-i])
для префикса каждого имени файла с заданной опцией, вы можете использовать здесь, чтобы вставить любой файл перед каждым файлом. Временный файл, содержащий пустую строку, можно сделать с помощью =(print)
, поэтому вы можете сделать:
() { cat file*.txt(P[$1]); } =(print)
В Linux или Cygwin вы также можете:
cat file*.txt(P[/dev/stdin]) <<< ''
Возможно, это не совсем то, что вы искали, но, как предложил Квазимодо в комментарии, GNU tail
может добавить пустую строку в дополнение к заголовку с именем файла:
$ echo 'this is foo' > foo.txt
$ echo 'this is bar' > bar.txt
$ tail -n+1 foo.txt bar.txt
==> foo.txt <==
this is foo
==> bar.txt <==
this is bar
-n+1
заставляет печатать весь файл; это означает «печатать хвост, начиная с первой строки».
Если вы хотите, чтобы заголовок добавлялся даже при наличии только одного файла для согласованности, вы можете использовать -v
.
$ tail -n+1 foo.txt
this is foo
$ tail -v -n+1 foo.txt
==> foo.txt <==
this is foo
Это не работает в POSIX /bin/sh
, но вbash
:
cat file1 <(echo) file2 >concatenated
<(echo)
заменяется временным именованным каналом, который подключается к выходным данным команды echo
, которая создает одну новую строку.