Последний подход с компиляцией in-VM кажется разумным и почти правильным. Однако я бы посоветовал сделать следующее :
./configure --prefix=/usr/local
Я не очень понимаю, почему вы решили установить префикс в каталоге /tmp. Он указывает на каталог, в который вы хотите установить приложение, я бы посоветовал придерживаться значения по умолчанию (не устанавливать его, или выбрать /usr/local
в качестве префикса)make
.
Здесь все в порядке. tar cfz /tmp/openvpn_compiled.tgz
tar xzf openvpn_compiled.tgz
make install
Теперь все должно работать отлично.
Когда вы переименовываете файл (типа каталога или другого), вы не изменяете его¹, поэтому время последнего изменения не меняется. Однако его статус изменениявремя (проверено -cmin
вместо -mmin
) обновляется (по крайней мере, в Linux, однако POSIX не дает никаких гарантий на это) .
Изменяются каталоги, из которых вы перемещаете файл (при удалении/переименовании записи в нем) и в (при добавлении/переименовании записи в нем). Время их изменения состояния также будет изменено.
Таким образом, если вам нужна эвристика для поиска последней переименованной директории, можно найти файл с самым последним ctime, ctime которого отличается от mtime.
Для zsh:
ctime_is_mtime() {
zmodload zsh/stat
local -A stat
zstat -H stat -- $REPLY &&
((stat[ctime] == stat[mtime]))
}
cd ./**/*(D/oc^+ctime_is_mtime[1])
Объяснение квалификаторов glob:
D
не пропускать скрытые файлы и каталоги/
рассматривать только файлы типа каталогoc
sort by ctime^
not+ctime_is_mtime
вызовите функцию для сравнения ctime с mtime.Обратите внимание, что степень детализации по времени снижается до секунды только в тех файловых системах, которые поддерживают гранулярность до доли секунды.
Другие случаи, когда ctime
изменяется, но не mtime
, включают любые изменения метаданных, кроме atime
при доступе (например, chmod
, chown
, setfacl
...), и использование touch
для установки произвольного времени модификации — еще один случай, когда ctime
и mtime
может оказаться другим.
¹ технически, для каталога, когда он перемещается в другой каталог, вы изменяете его ..
запись (которая теперь указывает на новый родительский каталог) для тех файловых систем, которые все еще хранят физические " ." и «..» записи в каталогах вместо их подделки на уровне ОС. Однако, AFAICT, системы по-прежнему не меняют mtime в этом случае.
Вы можете добавить это в свой файл .bashrc или .bash_aliases (или эквивалент, если ваша оболочка не bash
):
mvcd () {
mv -- "$1" "$2" &&
cd -P -- "$2"
}
Затем перезапустите вашу оболочку, затем вы можно использовать такую функцию:
mvcd foo bar
Предполагается, что $2
не является существующим каталогом, иначе mv
переместит $1
в его, а не на его (см. опцию -T
GNU mv
для защиты от этого).
--
отмечает конец опций. mv "$1" "$2"
будет mv "$option_or_source" "$option_or_argument_to_first_option_or_destination"
.mv -- "$1" "$2"
гарантирует, что $1
и $2
не рассматриваются как параметры, даже если их имя начинается с -
поэтому он всегда обрабатывается как mv -- "$source" "$destination"
. Как правило, вы хотите использовать --
везде, где команда получает произвольный аргумент.
-P
(для физическогообхода каталога) предназначен для предотвращения специальной обработки, которую cd
встроенный в оболочки POSIX выполняет по умолчанию с ..
компонентов пути, чтобы он обрабатывал содержимое $2
так же, как mv
. Без него в cdmv foo ../bar
, cd
можно было перейти в другой каталог bar
из одного mv
, переименованного в . ]foo
как.
Если вы установили $CDPATH
(или это было в среде при запуске оболочки), вам также необходимо отключить его для этого вызова cd
:
mvcd () {
mv -- "$1" "$2" &&
CDPATH= cd -P -- "$2"
}
Остаются некоторые дополнительные краеугольные проблемы: -
(и в некоторых оболочках -2
, +3
) обрабатываются особым образом даже после --
. Если вы хотите переименовать foo
в -
, используйте mvcd foo ./-
вместо. mvcd foo -
Для завершения, чтобы попытаться ответить без каких-либо настроек в системе, вы можете сделать следующее:
TARGET="tgt_name"; mv src_name ${TARGET}; cd ${TARGET}
Очевидно, вы можете выбрать более короткое имя переменной, например A
, но обратите внимание, что это может перезаписать переменные в вашем текущем сеансе. Если вас это беспокоит, подумайте о том, чтобы настроить среду для подоболочки:
env TARGET="tgt_name" bash -c 'mv src_name ${TARGET}; cd ${TARGET}'
Однако на данный момент я думаю, что мы более чем пересекли грань между удобством и сложностью, и было бы гораздо лучше настроить систему. с функцией mvcd из ответа Ли Райана.
В ksh93
и bash
:
$ pwd
/tmp
$ mkdir test_dir
$ mv test_dir another_name
$ cd $_
$ pwd
/tmp/another_name
$_
заменяется на последний аргумент предыдущей команды.
В качестве функции оболочки:
mvcd () {
mv -- "$1" "$2"
cd -P -- "$_"
}
Но вы также можете использовать
mvcd () {
mv -- "$1" "$2" &&
cd -P -- "$2"
}
, так как это позаботится о том, чтобы не пытаться изменить каталог, если mv
не удалось.
Двойной дефис необходим, чтобы разрешить имена, начинающиеся с дефиса. Двойной тире сигнализирует об окончании параметров командной строки и предотвращает интерпретацию имени как параметра в таких случаях.
Команда -P
с cd
необходима для того, чтобы cd
интерпретировала пути так же, как mv
(«физически» а не "логически"). Это позволяет избежать путаницы, когда новое местоположение указано с путем, который содержит ..
и пересекает символические ссылки.
Если вы перемещаете, а не просто переименовываете каталог, нужно будет разобраться со случаем, когда перемещение не связано с переименованием каталога:
mv some_dir existing_dir
Это приведет к перемещению some_dir
в существующий_каталог
, поэтому нужно
cd existing_dir/some_dir
изменить рабочий каталог на перемещенный каталог впоследствии.
Об этом позаботится следующая модифицированная функция оболочки:
mvcd () {
if [ -d "$2" ]; then
mv -- "$1" "$2" &&
cd -P -- "$2/$1"
else
mv -- "$1" "$2" &&
cd -P -- "$2"
fi
}
или "короче":
mvcd () {
if [ -d "$2" ] && mv -- "$1" "$2"; then
cd -P -- "$2/$1"
elif mv -- "$1" "$2"; then
cd -P -- "$2"
fi
}
Невозможно объединить mv
и cd
в действительно атомарный операция. Сначала должен произойти mv
, затем cd
, как бы вы на это ни смотрели, даже если вы написали это на C. Делая одно за другим (проверяя статус выхода of mv
) — правильный способ сделать это.
Вы можете изменить каталог перед вызовом mv
. Это оставляет оболочку в замешательстве относительно текущего рабочего каталога. Это безвредно для приложений, пока источник и цель находятся в одной и той же файловой системе, но оставляет переменную PWD
, встроенную функцию pwd
и подсказку, показывающую старое местоположение, среди прочего. Чтобы обновить pwd
и друзей в zsh и bash, вы можете использовать cd.
; но в других оболочках это ничего не делает, и вместо этого вам нужно cd `pwd -P`
; в обоих случаях это не сохраняет никакой информации о символических ссылках.
cd /some/where
mv "$PWD" /else/where
cd. # works in bash and zsh; use cd "`pwd`" in other shells
Вы можете опустить кавычки вокруг $PWD
, если он не содержит специальных символов оболочки. Вы не можете использовать .
в качестве источника mv
, потому что сам .
не может быть перемещен, для перемещения требуется «настоящая» запись в каталоге.
Преимущество этого решения состоит в том, что не требуется вводить какой-либо путь более одного раза, и оно устойчиво к mv
двум режимам работы, независимо от того, является ли его второй аргумент существующим каталогом или нет.
Вы можете запихнуть это в функцию, хотя основное преимущество этого подхода заключается в том, что он требует небольшого набора текста и не дает много пользы от функции. Если вы решите использовать функцию, я бы порекомендовал вместо этого один из подходов ниже.
Если вы сделаете все наоборот, решение с одним -лайнером придется пожертвовать многими случаями. Последним аргументом mv
может быть либо существующий каталог, и в этом случае источник перемещается в этот каталог и сохраняется его базовое имя, либо нет, и в этом случае конечное имя является целью. Вот функция, которая обрабатывает оба случая, оставаясь при этом простой (, а это значит, что она пропускает множество пограничных случаев ).
mvcd () {
mv "$@" &&
if [ $# -eq 2 ] && [ ! -d "$2" ]; then
cd "$2"
else
shift $(($#-2))
cd "$2/${1##*/}"
fi
}
Я использую более крупную и надежную функцию, которая устанавливает переменную moved
в список целевых файлов.Его все еще можно обмануть, но вам придется больше работать. Я когда-либо удосужился написать его только для zsh, но его можно было бы адаптировать для bash и ksh.
function mv {
emulate -LR zsh
setopt extended_glob
local i target=
moved=("$@")
while [[ $moved[1] == -* ]]; do
case $moved[1] in
-t?*) target=${moved[1]#*t};;
--t*=*) target=${moved[1]#*=};;
-t|--t*) target=$moved[2]; shift moved;;
-S|--su) shift moved;;
--) break;;
esac
shift moved
done
if [[ -z $target ]]; then
target=$moved[-1]
moved=($moved[1,-2])
fi
target=${target%%/##}
if [[ -d $target ]]; then
for ((i=1; i<=$#moved; i++)); do
moved[$i]=$target/${${moved[i]%%/##}##*/}
done
else
moved=($target)
fi
command mv "$@"
}
Затем, после команды mv
, я могу делать такие вещи, как ls -ld $moved
, cd $moved
, xdg-open $moved
(, это то, что я использую чаще всего )и т. д. Например,:
mvcd () {
mv "$@" && cd -- $moved[-1]
}