쉘 스크립트는 가장 많이 방문한 디렉토리를 인쇄합니다.

쉘 스크립트는 가장 많이 방문한 디렉토리를 인쇄합니다.

다음 기능을 사용하여 bash 스크립트를 작성하는 방법이 있습니까?

  1. 특정 키나 키 조합을 누르면 실행됩니다. (그렇게 중요한 요구사항은 아님)
  2. 지난 3시간 동안 가장 많이 방문한 디렉토리 7개를 식별합니다.
  3. 탭과 Shift-Tab(뒤로)을 사용하여 순환할 수 있도록 이 7개의 디렉터리 목록을 제공하세요. 그런 다음 Enter를 누르면 선택한 디렉토리로 CD를 이동하는 것을 의미합니다.

감사해요

답변1

파일 에 다음을 추가합니다 ~/.bashrc.

#### cd history mechanism ##############################################

export CDHISTFILE=~/.cdhistory
if [ -e "$CDHISTFILE" ]
then
    cdht=`mktemp`
    tail -500 "$CDHISTFILE" > $cdht
    mv "$cdht" "$CDHISTFILE"
fi

function keep_cd_history() {
    if [ -z "$1" ] ; then d="$HOME" ; else d="$1" ; fi
    cdhcan=`readlink -f "$d"`
    if 'cd' "$d"
    then
        echo -e `date +%s`"\t"$cdhcan >> $CDHISTFILE
    fi
}
function pick_cwd_from_history() {
    f=~/.cdhistgo
    cdhistpick "$f"
    if [ -r "$f" ] ; then cd "`head -1 $f`" ; fi
}

alias cd=keep_cd_history
alias cdh=pick_cwd_from_history

########################################################################

CD 기록 메커니즘의 사용자 정의 기록 파일이 마지막으로 본 이후 500줄보다 길어지면 첫 번째 부분에서 파일이 잘립니다. Bash의 내장 기록은 "지난 3시간 동안"의 동작을 얻는 데 필요한 타임스탬프를 포함하지 않기 때문에 사용할 수 없습니다.

이 두 Bash 함수는 아래 Perl 코드에서 수행할 수 없는 작업을 수행합니다. 그렇지 않으면 모든 무거운 작업을 수행하게 됩니다. 여기서 유일하게 까다로운 부분은 readlink사용하는 경로를 정규화하는 호출입니다. 기록 에 4개의 다른 항목이 아닌 cd $HOME ; cd ; cd ~ ; cd ../$USER동일한 경로의 4개 인스턴스가 있도록 이 작업을 수행해야 합니다.cd

별칭은 함수에 대한 편리한 래퍼일 뿐입니다.

이제 정말 까다로운 부분은 다음과 같습니다.

#!/usr/bin/perl -w
use strict;
use List::Util qw(min);

#### Configurables #####################################################

# Number of seconds back in time to look for candidate directories
my $history_seconds_threshold = 3 * 60 * 60;

# Ignore directories we have gone to less than this many times
my $access_count_threshold = 1;

# Number of directory options to give in pick list
my $max_choices = 7;


#### DO NOT OPEN. NO USER-SERVICEABLE PARTS INSIDE. ####################

# Get file name our caller wants the cd choice to be sent to
die "usage: $0 <choice_file>\n" unless $#ARGV == 0;
my $cdhg_file = $ARGV[0];
unlink $cdhg_file;      # don't care if it fails

# Build summary stats from history file to find recent most-accessed
my $oldest_interesting = time - $history_seconds_threshold;
my %stats;
open my $cdh, '<', "$ENV{HOME}/.cdhistory" or die "No cd history yet!\n";
while (<$cdh>) {
    chomp;
    my ($secs, $dir) = split /\t/;
    next unless $secs and $secs >= $oldest_interesting;
    ++$stats{$dir};
}

# Assemble directory pick list
my @counts = sort values %stats;
$access_count_threshold = $counts[$max_choices - 1] - 1
        if @counts > $max_choices;
my @dirs = grep { $stats{$_} > $access_count_threshold } keys %stats;
$max_choices = min($max_choices, scalar @dirs);

# Show pick list, and save response to the file pick_cwd_from_history()
# expects.  Why a file?  The shell must call chdir(2), not us, because
# if we do, we change only our CWD.  Can't use stdio; already in use.
my $choice;
if ($max_choices > 1) {
    for (my $i = 0; $i < $max_choices; ++$i) {
        print $i + 1, '. ', $dirs[$i], "\n";
    }
    print "\nYour choice, O splendid one? [1-$max_choices]: ";
    $choice = <STDIN>;
    chomp $choice;
    exit 0 unless $choice =~ /^[0-9]+$/ && $choice <= $max_choices;
}
elsif ($max_choices == 1) {
    print "Would you like to go to $dirs[0]? [y/n]: ";
    $choice = 1 if uc(<STDIN>) =~ /^Y/;
}
else {
    die "Not enough cd history to give choices!\n";
}
if ($choice) {
    open my $cdhg, '>', $cdhg_file or
            die "Can't write to $cdhg_file: $!\n";
    print $cdhg $dirs[$choice - 1], "\n";
}

이라는 파일에 저장하고 cdhistpick실행 가능하게 만든 다음 에 넣습니다 PATH. 직접 실행하지는 않습니다. cdh필요한 매개변수를 전달하므로 이에 대한 별명을 사용하십시오 pick_cwd_from_history().

어떻게 작동하나요? 글쎄요, 독자들을 위한 연습이요? :)

첫 번째 요구 사항(단축키)을 충족하려면 선택한 운영 체제에 적합한 매크로 기록 프로그램을 사용할 수 있습니다. 그냥 입력 cdh하고 누르기만 하면 됩니다. Enter또는 cdh입력하기 쉽기 때문에 직접 실행할 수도 있습니다.

Ctrl어디에서나 작동하는 간단하지만 기능이 덜 풍부한 대안을 원한다면 Bash의 역증분 검색 기능을 사용하는 습관을 가지세요 R. 해당 키를 누른 다음 "cd"(따옴표 없이 뒤에 공백 포함)를 입력하여 이전 cd명령으로 돌아갑니다. 그런 다음 Ctrl- 를 누를 때마다 이전 명령 R으로 돌아갑니다 . cd이렇게 하면 cdBash의 기록 기능 범위 내에서 지정한 모든 명령을 거꾸로 작업할 수 있습니다.

설명하다:

$ echo $HISTFILESIZE

Bash 기록이 얼마나 많은 명령줄을 저장할지 확인하세요. 3시간의 명령 기록을 저장하려면 이 값을 늘려야 할 수도 있습니다.

명령 기록을 뒤로 검색한 후 앞으로 검색하려면 Ctrl- 를 누르세요 S.

이것이 귀하의 시스템에서 작동하지 않는다면, 그 이유는 다음과 같습니다:소프트웨어 흐름 제어. 다음 명령을 사용하여 문제를 해결할 수 있습니다.

$ stty stop undef

이렇게 하면 Ctrl-S가 XOFF 문자로 해석되는 것을 방지할 수 있습니다.

그 결과 더 이상 Ctrl-S를 눌러 터미널 출력을 일시적으로 일시 중지할 수 없습니다. 개인적으로 마지막으로 의도적으로 사용한 것은 느린 모뎀 시절이었습니다. 요즘에는 빠른 스크롤링과 큰 스크롤백 버퍼의 출현으로 이 기능을 가끔씩만 사용한 다음 잠시 시간을 내어 눌러야 하는 것을 기억해야 합니다 Ctrl. Q그래야 터미널이 멈추지 않습니다. :)

답변2

사용이 스크립트. sqlite3사용하려면 설치해야 합니다 . 데이터베이스를 업데이트하기 위해 서브셸에서 sqlite3을 시작합니다(디렉터리 변경이 평소만큼 빠릅니다 cd). 디렉토리를 변경하려면 명령을 사용하여 이 스크립트를 다운로드하세요 source. 인수가 제공되지 않으면 지난 이틀 동안 가장 많이 방문한 디렉토리의 정렬된 목록이 bash에 표시됩니다. 하나를 선택할 수 있습니다..bashrccc

관련 정보