Можно использовать дескриптор файла чтения-записи удара для открытия файла (для перезаписи его на месте), затем sed
и truncate
... но конечно, никогда не позволяйте Вашим изменениям быть больше, чем чтение объема данных до сих пор.
Вот сценарий (использование: колотите переменный $BASHPID),
# Create a test file
echo "going abc" >junk
echo "going def" >>junk
echo "# ORIGINAL file";cat junk |tee >( wc=($(wc)); echo "# ${wc[0]} lines, ${wc[2]} bytes" ;echo )
#
# Assign file to fd 3, and open it r/w
exec 3<> junk
#
# Choose a unique filename to hold the new file size and the pid
# of the semi-asynchrounous process to which 'tee' streams the new file..
[[ ! -d "/tmp/$USER" ]] && mkdir "/tmp/$USER"
f_pid_size="/tmp/$USER/pid_size.$(date '+%N')" # %N is a GNU extension: nanoseconds
[[ -f "$f_pid_size" ]] && { echo "ERROR: Work file already exists: '$f_pid_size'" ;exit 1 ; }
#
# run 'sed' output to 'tee' ...
# to modify the file in-situ, and to count the bytes
<junk sed -e "s/going //" |tee >(echo -n "$BASHPID " >"$f_pid_size" ;wc -c >>"$f_pid_size") >&3
#
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# The byte-counting process is not a child-process,
# so 'wait' doesn't work... but wait we must...
pid_size=($(cat "$f_pid_size")) ;pid=${pid_size[0]}
# $f_pid_size may initially contain only the pid...
# get the size when pid termination is assured
while [[ "$pid" != "" ]] ; do
if ! kill -0 "$pid" 2>/dev/null; then
pid="" # pid has terminated. get the byte count
pid_size=($(cat "$f_pid_size")) ;size=${pid_size[1]}
fi
done
rm "$f_pid_size"
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#
exec 3>&- # close fd 3.
newsize=$(cat newsize)
echo "# MODIFIED file (before truncating)";cat junk |tee >( wc=($(wc)); echo "# ${wc[0]} lines, ${wc[2]} bytes" ;echo ) cat junk
#
truncate -s $newsize junk
echo "# NEW (truncated) file";cat junk |tee >( wc=($(wc)); echo "# ${wc[0]} lines, ${wc[2]} bytes" ;echo ) cat junk
#
exit
Вот тестовый вывод
# ORIGINAL file
going abc
going def
# 2 lines, 20 bytes
# MODIFIED file (before truncating)
abc
def
c
going def
# 4 lines, 20 bytes
# NEW (truncated) file
abc
def
# 2 lines, 8 bytes
Это зависит полностью от того, как оболочка принимает решение обработать его
bash
по умолчанию перезапишет файл истории с локальной историей каждой оболочки, поскольку это выходит, таким образом, последняя оболочка для выхода из побед. histappend
опция заставит это добавлять к основной истории вместо этого (shopt -s histappend
).
zsh
делает то же по умолчанию и имеет несколько опций для контакта с ним:
appendhistory
- История каждой оболочки добавляется в основной файл истории, поскольку оболочка выходитincappendhistory
- Основной файл истории обновляется каждый раз, когда строка выполняется в любой оболочке, вместо того, чтобы ожидать до той оболочки выходыsharehistory
- Как incappendhistory
, но также и получения по запросу изменяются из основного файла истории во все рабочие оболочки, таким образом, можно выполнить команду в одной оболочке и затем подбросить ударом в другой оболочке и видеть егоЯ первоначально получил эту идею от O'Reilly "книга" Электроинструментов Unix.
В моем .profile
Я установил:
export HISTFILE=$HOME/.sh_hist.$$
Каждый раз мой .profile
читается, я получаю новый файл истории, названный с PID моей сессии. Если у меня есть несколько логинов, каждый вход в систему получает уникальный файл истории. Работы в ksh
и bash
.
Если Вы просто открываете новые терминалы на X сессиях, это обычно не оболочки входа в систему, но можно настроить их для действия как оболочки входа в систему. Например, rxvt +ls
запустится rxvt
как оболочка входа в систему. Проверьте документы на любой терминал, который Вы используете.
Кроме того, если Вы не используете a .logout
или .bash_logout
файл (или некоторые другие средства) для чистки у Вас в конечном счете будет crapload .sh_hist
файлы.
shopt -s histappend
не работают? – Michael Mrozek♦ 15.10.2010, 17:18