Большинство нельдов не имеет понятия времени создания файла. Вы не можете сделать ls
распечатайте его, потому что информация не зарегистрирована. При необходимости во времени создания используйте систему управления версиями: определите время создания как время регистрации.
Если Ваш вариант Unix имеет время создания, посмотрите на его документацию. Например, на Mac OS X (единственный пример я знаю о ¹), использовать ls -tU
. Windows также хранит время создания, но он не всегда выставляется портам утилит Unix, например, Cygwin ls
не имеет опции показать его. stat
утилита может показать время создания, названное “время рождения” в утилитах GNU, таким образом, под Cygwin можно показать файлы, отсортированные по рождению время с stat -c '%W %n' * | sort -k1n
.
Обратите внимание что ctime (ls -lc
) не время создания файла, это - время изменения inode. Время изменения inode обновляется каждый раз, когда что-либо об изменениях файла (содержание или метаданные) за исключением того, что ctime не обновляется, когда файл просто читается (даже если atime обновляется). В частности, ctime всегда более свеж, чем mtime (время изменения содержания файла), если mtime не был явно установлен на дату в будущем.
Еще более общая версия, которая позволяет использовать find
опции:
#!/bin/bash
set -e
path="$1"
shift 1
while [[ $path != / ]];
do
find "$path" -maxdepth 1 -mindepth 1 "$@"
# Note: if you want to ignore symlinks, use "$(realpath -s "$path"/..)"
path="$(readlink -f "$path"/..)"
done
Например (принимающий сценарий сохраняется как find_up.sh
)
find_up.sh some_dir -iname "foo*bar" -execdir pwd \;
... распечатает названия всего из some_dir
предки (включая себя) до /
в котором найден файл с шаблоном.
При использовании readlink -f
вышеупомянутый сценарий будет следовать за символьными ссылками на пути, как отмечено в комментариях. Можно использовать realpath -s
вместо этого, если Вы захотите продолжить, то пути по имени ("/foo/bar" подойдет к "нечто", даже если "панель" будет символьной ссылкой) - однако, который требует установки realpath
который не установлен по умолчанию на большинстве платформ.
git rev-parse --show-toplevel
распечатает высокоуровневый каталог текущего репозитория, если Вы будете в одном.
Другие связанные опции:
# `pwd` is inside a git-controlled repository
git rev-parse --is-inside-work-tree
# `pwd` is inside the .git directory
git rev-parse --is-inside-git-dir
# path to the .git directory (may be relative or absolute)
git rev-parse --git-dir
# inverses of each other:
# `pwd` relative to root of repository
git rev-parse --show-prefix
# root of repository relative to `pwd`
git rev-parse --show-cdup
Обобщенная версия ответа Gilles, первый параметр раньше находил соответствие:
find-up () {
path=$(pwd)
while [[ "$path" != "" && ! -e "$path/$1" ]]; do
path=${path%/*}
done
echo "$path"
}
Сохраняет использование символьных ссылок.
Находка не может сделать этого. Я не могу думать ни о чем более простом, чем цикл оболочки. (Непротестированный, предполагает, что существует нет /.git
)
git_root=$(pwd -P 2>/dev/null || command pwd)
while [ ! -e "$git_root/.git" ]; do
git_root=${git_root%/*}
if [ "$git_root" = "" ]; then break; fi
done
Для конкретного случая репозитория мерзавца можно позволить мерзавцу сделать работу для Вас.
git_root=$(GIT_EDITOR=echo git config -e)
git_root=${git_root%/*}
При использовании zsh с расширенным включенным globbing можно сделать это с остротой:
(../)#.git(:h) # relative path to containing directory, eg. '../../..', '.'
(../)#.git(:a) # absolute path to actual file, eg. '/home/you/src/prj1/.git'
(../)#.git(:a:h) # absolute path to containing directory, eg. '/home/you/src/prj1'
Объяснение (заключенный в кавычки из man zshexpn
):
Рекурсивный Globbing
Компонент пути формы
(foo/)#
соответствует пути, состоящему из нуля или большего количества каталогов, соответствующих нечто шаблона. Как стенография,**/
эквивалентно(*/)#
.Модификаторы
После дополнительного указателя слова можно добавить последовательность одного или нескольких следующих модификаторов, каждый, которому предшествует a ':'. Эти модификаторы также работают над результатом поколения имени файла и расширения параметра, кроме, где отмечено.
- a
- Превратите имя файла в полный путь: предварительно ожидает текущий каталог, при необходимости, и разрешает любое использование '..' и '.'
- A
- Как, но также и использование твердости символьных ссылок, если это возможно. Отметьте то разрешение '..' происходит перед разрешением символьных ссылок. Этот вызов эквивалентен, если Ваша система не имеет
realpath
системный вызов (современные системы делают).- h
- Удалите запаздывающий компонент пути, оставив голову. Это работает как'
dirname
'.
Кредиты: Faux
на #zsh
для начального предложения использования (../)#.git(:h)
.
(../)
делает... О, и кто/какой Faux on #zsh
?
– alex gray
20.03.2015, 17:05
(../)
один не означает много, но (../)#
средства пытаются развернуть шаблон в круглой скобке 0 или больше раз и только использовать тех, которые на самом деле существуют в файловой системе. Поскольку мы расширяемся от 0 до n родительских каталогов, мы эффективно ищем вверх на корень файловой системы (примечание: Вы, вероятно, хотите добавить что-то после того, как шаблон для создания этого значимым, но для просвещения выполнится print -l (../)#
). И #zsh
канал IRC, Faux
имя пользователя на нем. Faux
предложенный решение, поэтому кредит.
– unthought
22.03.2015, 13:03
(../)#.git(/Y1:a:h)
для остановки в первом найденном одного (с последней версией zsh),
– Stéphane Chazelas
08.06.2015, 23:43
setopt extended_glob
– Shlomi
24.09.2015, 11:40
Эта версия findup поддерживает синтаксис «find», как в ответе @ sinelaw, но также поддерживает символические ссылки без необходимости использования реального пути. Он также поддерживает необязательную функцию «остановить в», так что это работает: findup.: ~ -Name foo
... ищет foo без передачи домашнего каталога.
#!/bin/bash
set -e
# get optional root dir
IFS=":" && arg=($1)
shift 1
path=${arg[0]}
root=${arg[1]}
[[ $root ]] || root=/
# resolve home dir
eval root=$root
# use "cd" to prevent symlinks from resolving
cd $path
while [[ "$cur" != "$root" && "$cur" != "/" ]];
do
cur="$(pwd)"
find "$cur/" -maxdepth 1 -mindepth 1 "$@"
cd ..
done
Я обнаружил, что работа с символическими ссылками убивает некоторые другие параметры. Особенно конкретные ответы git. Я наполовину создал свой собственный фаворит из этого оригинального ответа, который довольно эффективен.
#!/usr/bin/env bash
# usage: upsearch .git
function upsearch () {
origdir=${2-`pwd`}
test / == "$PWD" && cd "$origdir" && return || \
test -e "$1" && echo "$PWD" && cd "$origdir" && return || \
cd .. && upsearch "$1" "$origdir"
}
Я использую символические ссылки для своих проектов go, потому что go требует, чтобы исходный код находился в определенном месте, и мне нравится хранить свои проекты в ~ / projects. Я создаю проект в $ GOPATH / src и привязываю его к ~ / projects. Таким образом, запуск git rev-parse --show-toplevel
распечатывает каталог $ GOPATH, а не каталог ~ / projects. Это решение решает эту проблему.
Я понимаю, что это очень специфическая ситуация, но думаю, что решение ценное.
Я модифицировал решение sinelaw , чтобы оно соответствовало POSIX. Он не следует символическим ссылкам и включает поиск в корневом каталоге с использованием цикла do while.
find-up:
#!/usr/bin/env sh
set -e # exit on error
# Use cd and pwd to not follow symlinks.
# Unlike find, default to current directory if no arguments given.
directory="$(cd "${1:-.}"; pwd)"
shift 1 # shift off the first argument, so only options remain
while :; do
# POSIX, but gets "Permission denied" on private directories.
# Use || true to allow errors without exiting on error.
find "$directory" -path "${directory%/}/*/*" -prune -o ! -path "$directory" "$@" -print || true
# Equivalent, but -mindepth and -maxdepth aren't POSIX.
# find "$directory" -mindepth 1 -maxdepth 1 "$@"
if [ "$directory" = '/' ]; then
break # End do while loop
else
directory=$(dirname "$directory")
fi
done
Рекурсия может привести к весьма краткому решению.
#!/usr/bin/env bash
parent-find() {
local file="$1"
local dir="$2"
test -e "$dir/$file" && echo "$dir" && return 0
[ '/' = "$dir" ] && return 1
parent-find "$file" "$(dirname "$dir")"
}
# Example
parent-find.bashrc "/home/user/projects/parent-find"
# should respond with "/home/user"
Так как есть вкладыш zsh one -, вот более общий вкладыш unix oneish -для поиска в 3 родительских каталогах:
$ name=fileOrDirName
$ eval find./$(printf "{$(echo %{1..4}q,)}" | sed 's/ /\.\.\//g')/ -maxdepth 1 -name $name
Я признаю, что это не самая красивая команда, но это одна строка. Для поиска 4 каталогов вверх замените echo %{1..4}q,
на echo %{1..5}q,
. Укажите имя файла или каталога с помощью переменной name.
Короче говоря, $(printf... | sed...)
заменяется на его вывод с использованием подстановки команд , который затем расширяется с помощью find
с использованием раскрытия фигурных скобок . В разбивке на две команды это выглядит так (с копией и вставкой посередине):
$ printf "{$(echo %{1..4}q,)}" | sed 's/ /\.\.\//g'
{'',../'',../../'',../../../'',}
$ #copy and paste the output
$ find./{'',../'',../../'',../../../'',} -maxdepth 1 -name $name
Вы можете узнать больше о расширениях оболочки в man bash
или в ресурсах ниже на веб-сайте gnu
realpath -s
для получения поведения, Вы хотите. – sinelaw 06.06.2015, 23:53