Мне кажется, что у вас неправильное имя репозитория. Я не вижу google-cloud-monitoring-bionic
.
Возможно ли это google-cloud-monitoring-xenial
?
Просмотрите https://packages.cloud.google.com/apt/dists
в веб-браузере, чтобы просмотреть доступные репозитории.
Если вы согласны с созданием нового каталога в папке /tmp
, вы можете использовать команду find, этот метод также позаботится о печати только уникальных имен каталогов.
#!/bin/bash
if [[ $# -eq 0 ]]; then exit; fi
mkdir -p /tmp/printnames
for i
do
mkdir -p /tmp/printnames/"$i"
done
cd /tmp/printnames
find * -type d -print
rm -r /tmp/printnames
Таким образом, вы можете создать временную структуру каталогов, а затем перемещаться по ней с помощью find.
Сценарий Python, использующий стандартный модуль pathlib
, работающий с аргументами вместо ввода:
#! /usr/bin/env python3
import sys
from collections import OrderedDict
from pathlib import Path
paths = OrderedDict() # to maintain ordering and skip duplicates
for arg in sys.argv[1:]:
path = Path(arg)
for subpath in reversed(path.parents):
# add the parents
paths[subpath.as_posix()] = subpath
# add the path itself
paths[path.as_posix()] = path
# we don't need '.' in the output
if '.' in paths:
paths.pop('.')
print('\n'.join(paths.keys()))
(Можно было бы легко модифицировать его для использования stdin, зациклив вместо этого sys.stdin
.)
Пример:
%./foo.py dir1/file1 dir1/file2 foo/bar/moocow
dir1
dir1/file1
dir1/file2
foo
foo/bar
foo/bar/moocow
Этот код сделает это. Он не использует временные файлы. Он работает с пробелами, однако новые строки неоднозначны (измените \n
на \0
, чтобы исправить ). Вы должны использовать \0
, если он будет использоваться в автоматизированных процессах. \0
— единственный символ, который гарантированно не встречается в имени файла Unix.
Он просто рекурсивно использует dirnames
. Вы можете настроить его, удалив/включив некоторые из printf
s. Чтобы сделать его восходящим или нисходящим, или чтобы не отображать корневой узел(.
или/
). В вашем примере не было показа корневого узла, но я думаю, что он нужен. Без него /a/b/c
дает тот же результат, что и a/b/c
.
#!/bin/bash
function dirnames {
local input
local parent
input="$1"
if [[ "$input" == "" ]]
then
true
elif [[ "$input" == "." || "$input" == "/" ]]
then
printf '%s\n' "$input" #print the root node
else
#printf '%s\n' "$input" #print node (descending)
parent="$(dirname "$input")"
dirnames "$parent"
printf '%s\n' "$input" #print node (ascending)
fi
}
for d in "$@"
do
dirnames "$d"
done
Пример использования
%↳./dirnames a/b/c
.
a
a/b
a/b/c
%↳./dirnames /a/b/c
/
/a
/a/b
/a/b/c
%↳
Чтобы заставить его работать вот так
%↳./dirnames a/b/c
.
a
b
c
%↳./dirnames /a/b/c
/
a
b
c
%↳
, затем сохраните файл как dirnames
, затем запустите sed -r -i '17 s/("[$]input")/"$(basename \1)"/' dirnames
. Теперь у вас будет скрипт, который выводит только листья на каждом уровне.
Учитывая, что вы собираетесь обрабатывать пути как текст, с неявными предположениями, что они не будут содержать символы новой строки и что их не нужно канонизировать, вы можете направить их в этот скрипт:
#!/bin/awk -f
BEGIN {
FS="/"
}
{
f = ""
for (i=1; i<=NF; i++) {
f = f (i>1 ? FS : "") $i
if (! p[f]++ && f)
print f
}
}
Каждая строка ввода разбивается на /
. Затем поля объединяются с первого по последнее, разделенные символом /
, и каждый промежуточный результат(f
фрагмента )сохраняется как значение индекса ассоциативного массива(p
aths ). Печатается каждый не-пустой 1 фрагмент, который еще не встречался.
Обратите внимание, что foo
, /foo
, foo/
, /foo/
и даже /foo//
будут считаться отдельными путями, и все они будут распечатаны отдельно.
1Первый в абсолютных путях, которые в AWK имеют пустое поле перед первым/
Если вы не возражаете против отсортированного вывода, вы можете получить хороший результат с конвейером, используя sed
скрипт плюс sort
вот так:
$ sed -nE 's%/+(/[^/]|$)%\1%g;:loop;\%(^[^/]+|/[^/]*)$%{p;s///};tloop' | LC_ALL=C sort -u
Приведенный выше сценарий Sed доходит до степени объединения смежных /
символов (самая первая s
команда до первой ;
делает это ), но кроме этого он не знает относительного дорожки и т. д.
Обратите внимание, что сценарий совместим с POSIX, хотя в некоторых системах вам может потребоваться ввести его в несколько строк, например, так:
$ sed -nE 's%/+(/[^/]|$)%\1%g
:loop
\%(^[^/]+|/[^/]*)$%{
p;s///
}
tloop
' | LC_ALL=C sort -u
Также обратите внимание, что он не может обрабатывать новые строки в именах файлов. Однако в расширенных инструментах, поддерживающих параметр -z
, вы можете просто добавить его как к sed
, так и к sort
, чтобы получить ввод-вывод с нулевым -разделителем.
Мне также понравилось создавать сценарий, способный к полной канонизации, включая любые произвольные вхождения .
и ..
, а также неквалифицированные пути, такие как dir1/file1
с предшествующим ./
. Однако он не разрешает символические ссылки, поскольку вообще не обращается к файловой системе.
Я использовал Awk из-за его полезных встроенных механизмов для разделения и перестроения строк.
#!/usr/bin/awk -f
BEGIN { FS="/+"; OFS="/" }
{
for (nfields=dotdot=0; NF; NF--) {
if (path[nfields]=$NF) {
if ($NF=="..") dotdot++
else if ($NF!=".") {
if (dotdot) dotdot--
else nfields++
}
}
}
if (nfields in path && !path[nfields])
$1=""
else {
while (dotdot--) path[nfields++]=".."
path[nfields++]="."
}
while (nfields--) {
$(NF+1) = path[nfields]
if (!seen[$0]++) print $0
}
}
Вы можете обрабатывать новые строки в именах файлов, вызывая их с помощью -v RS='\0' -v ORS='\0'
в реализациях Awk (, таких как GNU Awk ), которые поддерживают nul RS
.
ХТХ