Linux에서 실행되고 쉘(bash뿐만 아니라)과 파일 시스템(drvfs 또는 btrfs 포함) 간에 이식 가능한 솔루션을 원합니다. 참고: 디렉토리 이름에는 공백이 포함될 수 있습니다.
find를 사용하면 다음과 같이 폴더에 루트가 있는 모든 경로 목록을 생성할 수 있습니다.
find -type d
.
./a dir
./a dir/20210101
./a dir/20210101/bin
./a dir/20210101/etc
./a dir/20210101/var
./a dir/20210101/var/log
./a dir/20211201
./b dir
./b dir/20210212
./b dir/20210212/bin
./b dir/20210212/etc
./c dir
./d dir
./d dir/20210711
그러나 가장 깊은 고유 경로에 이미 포함되어 있는 "기본" 또는 "상위" 경로를 제외하고 싶습니다. 또한 최선의 설명을 사용하고 있지 않은 것 같으니 올바른 용어를 사용하여 설명하도록 도와주세요.
기본 스크립트를 사용하여 이 작업을 수행할 수 있지만 더 우아한 방법이 있다고 가정하면 다음 중 하나를 사용하세요.
- 찾다
- 엘에스
이것은 내 스크립트입니다.
save_ifs=$IFS;
IFS=$'\n';
prev_path="";
for path in $(find -depth -type d); do
if [ ! ${#path} -lt ${#prev_path} ]; then
echo $path;
fi
prev_path=$path;
done
그리고 그 출력 - 이것은 원하는 출력입니다
./a dir/20210101/bin
./a dir/20210101/etc
./a dir/20210101/var/log
./a dir/20211201
./b dir/20210212/bin
./b dir/20210212/etc
./c dir
./d dir/20210711
답변1
이건 반대의 변형인거 같은데바로 이전 경로보다 더 깊은 텍스트 파일의 경로를 필터링합니다..
따라서 내 답변을 수정하면 다음과 같은 옵션이 있습니다.
tac input.txt | awk '
{ sub(/\/?$/, "/") }
NR == 1 || substr(prev, 0, length($0)) != $0 { print }
{ prev = $0 }; ' | tac | sed -e 's/\/$//'
또는
cat input.txt | awk '
{ sub(/\/?$/, "/") }
NR != 1 && substr($0, 0, length(prev)) != prev {print prev}
{ prev = $0 }
END { print }; ' | sed -e 's/\/$//'
첫 번째 목록의 입력에 따라 둘 다 다음을 제공합니다.
./a dir/20210101/bin
./a dir/20210101/etc
./a dir/20210101/var/log
./a dir/20211201
./b dir/20210212/bin
./b dir/20210212/etc
./c dir
./d dir
디렉토리의 내용이 해당 디렉토리 바로 뒤에 오도록 입력이 정렬되었다고 가정하면(예: 깊이 우선, 사전 정렬) 이 출력은 (*)find
의 내용 과 유사해야 하며 C 언어의 사전 정렬과 일치해야 합니다. 줄게.
-depth
( 당신이 사용하지 않는 한
답변2
편집하다: 답장을 다시 작성하면 코드는 변경되지 않습니다.
이것기본
깊이 우선 검색은 find . -type d
하위 디렉터리 앞에 상위 디렉터리(있는 경우)를 출력하므로 하위 디렉터리(추가 하위 디렉터리) 바로 다음 줄은 건너뜁니다. 이것은 POSIX를 사용한 한 줄의 코드입니다.sed스크립트. 경로 이름에는 개행 문자가 없는 것으로 간주됩니다.
find . -type d | sed -e '$!N' -e '/\(.*\)\n\1\//!P' -e 'D'
어디:
- 표준
N; …; P; D;
명령 시퀀스는 입력을 위해 슬라이딩 두 줄 창을 엽니다. - 마지막 줄( )이 아닌 이상 + 다음 줄을 패턴 공간( ) 에
$!
추가합니다 .\n
N
- 두 번째 줄이 첫 번째 줄과 일치하지 않으면
/
(\1\/
) 다음에 첫 번째 줄을 인쇄합니다 (P
) - 첫 번째 행을 삭제하고 루프를 다시 시작합니다(
D
)