답변:
으로 @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->iterateglibc가 readdir()결국 via로 필터링 하는 호출 getdents()은 파일 시스템 특정 구현에 매핑됩니다. 더 높은 수준 dirent에서 fs 구현이 반환 하는 순서를 바꾸는 것을 볼 수 없습니다 .
stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'