답변:
으로 @samiam는 진술했다 목록을 통해 반 임의의 순서로 당신에게 반환됩니다 readdir()
. 다음을 추가하겠습니다.
반환 된 목록은 내가 디렉토리 순서라고 부르는 것입니다. 이전 파일 시스템에서 순서는 종종 디렉토리 테이블의 파일 항목이 추가 된 작성 순서입니다. 물론 디렉토리 항목을 삭제하면이 항목이 재활용되므로 저장된 후속 파일이 이전 항목을 대체하므로 순서는 더 이상 작성 시간을 기준으로하지 않습니다.
디렉토리 데이터 구조가 검색 트리 또는 해시 테이블을 기반으로하는 최신 파일 시스템에서는 실제로 순서를 예측할 수 없습니다.
touch 명령을 실행할 때 생성 된 파일을 찌르면 다음 inode가 할당 된 것으로 나타납니다.
$ touch dir/{{1..8},{a..p}}
$ stat --printf="%n -- %i\n" dir/*
dir/1 -- 10883235
dir/2 -- 10883236
dir/3 -- 10883242
dir/4 -- 10883243
dir/5 -- 10883244
dir/6 -- 10883245
dir/7 -- 10883246
dir/8 -- 10883247
dir/a -- 10883248
dir/b -- 10883249
dir/c -- 10883250
dir/d -- 10883251
dir/e -- 10883252
dir/f -- 10883253
dir/g -- 10883254
dir/h -- 10883255
dir/i -- 10883256
dir/j -- 10883299
dir/k -- 10883302
dir/l -- 10883303
dir/m -- 10883311
dir/n -- 10883424
dir/o -- 10883426
dir/p -- 10883427
터치에 의해 사용 된 괄호 확장은 파일 이름을 알파벳 순서로 생성하므로 HDD에 기록 될 때 순차적 inode 번호가 할당됩니다. 그러나 디렉토리의 순서에는 영향을 미치지 않습니다.
tar
명령을 여러 번 실행 하면 목록에 순서가 있음을 나타내는 것 같습니다. 명령을 여러 번 실행하면 매번 동일한 목록이 생성되기 때문입니다. 여기에서 나는 그것을 100 번 실행 한 다음 실행을 비교했으며 모두 동일합니다.
$ for i in {1..100};do tar cJvf file.tar.xz dir/ > run${i};done
$ for i in {1..100};do cmp run1 run${i};done
$
전략적으로 say를 삭제 dir/e
한 다음 새 파일을 추가하면 dir/ee
이 새 파일이 dir/e
디렉토리 항목 테이블에서 이전에 차지한 위치를 차지 했음을 알 수 있습니다 .
$ rm dir/e
$ touch dir/ee
이제 for
위 의 루프 중 하나의 출력을 유지합시다 .
$ mv run1 r1A
이제 명령을 다시 100 번 실행하는 for
루프를 tar
다시 실행하고이 두 번째 실행을 이전 실행과 비교하십시오.
$ sdiff r1A run1
dir/ dir/
...
dir/c dir/c
dir/f dir/f
dir/e | dir/ee
dir/o dir/o
dir/2 dir/2
...
우리는 통지 dir/ee
취한 dir/e
디렉토리 테이블의 장소.
readdir()
원래. 타르 파일이 디렉토리에 무엇을 발견하면 직접 통해 나열하는 파일에 대한 커널 요청 opendir()
에 의해 다음을 readdir()
. readdir()
특정 순서로 파일을 반환하지 않습니다. 파일 순서는 Linux 커널에서 사용하는 파일 시스템에 따라 다릅니다.
아아, tar
하위 디렉토리에서 파일을 정렬 하는 옵션은 아닙니다 (파일을 추가하는 것은 독자의 연습으로 남습니다).
f_op->iterate
glibc가 readdir()
결국 via로 필터링 하는 호출 getdents()
은 파일 시스템 특정 구현에 매핑됩니다. 더 높은 수준 dirent
에서 fs 구현이 반환 하는 순서를 바꾸는 것을 볼 수 없습니다 .
stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'