
Например, у меня есть много файлов, которые выглядят как вывод ниже, я пытаюсь получить список всех уникальных имен файлов, но игнорирую символы справа от "-". Я пробовал ls -la | grep ....- | sort --unique
и некоторые вариации, но это не дает нужного мне вывода
4855-00160880.psi
4855-00160980.ps
4855-00160980.psi
5355-00160880.ps
5355-00160880.psi
5355-00160980.ps
5355-00160980.psi
5855-00160880.ps
5855-00160880.psi
5855-00160980.ps
5855-00160980.psi
5855-00160A80.ps
5855-00160A80.psi
В идеале я хотел бы, чтобы вывод показывал что-то вроде
4855
5355
5855
решение1
СВы действительно не хотите анализироватьls
, это должно сработать:
find . -type f -maxdepth 1 -exec basename "{}" \; | cut -d'-' -f1 | sort -u
решение2
Как это?
printf "%-4.4s\n" ????-* | uniq
Оболочка расширяет подстановочный знак в алфавитном порядке и передает результат в качестве аргументов в printf
. Строка формата обрезает каждый аргумент до четырех символов и добавляет новую строку. Теперь остается только удалить смежные дубликаты.
Если вы не знаете количество цифр перед дефисом, но у вас есть идея, вы можете перебрать несколько кандидатов:
for expr in '??' '???' '????' '?????' # Quoted (!)
do
printf "%-${#expr}.${#expr}\n" $expr-* | # Unquoted!
uniq
done
Здесь используется только Bashрасширение параметра $[#var}
который получает длину строки $var
.
Обратите внимание на трюк с кавычками подстановочных знаков, чтобы избежать их расширения при инициализации цикла, а затем на использование переменной без кавычек внутри цикла (что является табу в большинстве других случаев).
решение3
Стоит добавить -type f
к ответу DopeGhoti, чтобы избежать этого фиктивного .
результата.
find . -maxdepth 1 -exec basename "{}" \; | cut -d'-' -f1 | sort -u
.
4855
5355
5855
find . -maxdepth 1 -type f -exec basename "{}" \; | cut -d'-' -f1 | sort -u
4855
5355
5855
$
Если вы хотите сохранить схожесть с вашей первоначальной попыткой, вы можете использовать это ( ls
хотя это плохо, так как это анализирует!)
ls -1 | grep ^....- | cut -c1-4 | sort --unique
Решение на основе awk, все еще анализирует ls
ls -1 | awk -F- '{print $1}' | sort --unique
В каждом из этих случаев нет необходимости выполнять сортировку, поскольку ls
вывод уже отсортирован, поэтому можно просто использовать uniq
.
ls -1 | awk -F- '{print $1}' | uniq
решение на основе sed
ls -1 | sed 's/-.*//' | uniq
найти / sed решение, которое избегает разбора ls
find . -type f -printf "%f\n" | sed 's/-.*//g' | sort --unique
Если перед "-" всегда 4 цифры, то это довольно элегантно.
find . -type f -printf "%.4f\n" | sort -u
решение4
С zsh
:
myfiles=(*-*(.))
print -rl -- ${(u)myfiles[@]%%-*}
Это сохраняет все обычные имена файлов, которые содержат хотя бы один тире в массиве. Затем он использует расширение параметра для каждого элемента массива, чтобы удалить первый тире и все, что следует за ним. Все повторяющиеся элементы удаляются с помощью флага (u)
.
Чтобы выбрать также скрытые файлы, используйтеmyfiles=(*-*(.D))