파일이나 폴더의 크기를 바이트 단위로 가져오는 POSIX 호환 방법은 무엇입니까?

파일이나 폴더의 크기를 바이트 단위로 가져오는 POSIX 호환 방법은 무엇입니까?

Open Group 사양에 따르면 POSIX는du-b크기를 바이트 단위로 표시하는 옵션 은 없습니다 . 그렇다면 파일이나 폴더의 크기를 바이트 단위로 가져오는 POSIX 호환 방법은 무엇입니까?

답변1

duGNU가 수행하는 작업을 대략적으로 설명 -sb하면 다음과 같습니다.

cumulative_size() (
  export LC_ALL=C
  ret=0
  [ "$#" -gt 0 ] || set .
  for file do
    case $file in
      (/*) sanitized=$file;;
      (*) sanitized=./$file;;
    esac
    size=$(
      find "$sanitized" ! -type b ! -type c -exec ls -niqd {} + |
        awk '! seen[$1]++ {sum += $6}
             END {print sum}'
    )
    if [ -n "$size" ]; then
      printf '%s\t%s\n' "$size" "$file"
    else
      ret=1
    fi
  done
  exit "$ret"
)

GNU와 마찬가지로 du파일의 inode 번호를 보고 ls -ni파일 수를 한 번만 계산 하려고 합니다(첫 번째 필드에 보고된 대로).장치 아이디ls디렉터리 계층 구조가 여러 파일 시스템에 걸쳐 있지 않다고 가정하여 보고 할 수 없습니다 .

이와 대조적으로 du파일별 매개변수에서만 중복을 제거합니다.

예를 들어:

cumulative_size dir dir

의 누적 디스크 사용량과 해당 내용은 dir두 번 보고되며, 파일 내의 각 파일은 한 번만 계산되는 반면, GNU는 디스크 사용량을 한 번만 du -bs보고합니다 .dir

장치 파일 ls -n의 크기가 보고되지 않으므로 제외합니다. 적어도 Linux에서는 크기가 항상 0.

find술어 로 시작하거나 -해당 술어와 일치하는 이름으로 시작하는 파일 경로는 제공할 수 없습니다( !, ...도 포함). (여기서는 파일 경로가 ./로 시작하지 않는 경우 접두사를 추가하여 이 문제를 해결합니다 /. 따라서 는 find !또는 find -print가 됩니다 . 로 시작하는 조건자가 구현에 없다고 가정합니다 . 이는 옵션의 끝을 표시하기 위해 에 전달할 필요가 없다는 것을 의미합니다 .find ./!find ./-printfind/--ls

우리는 uid/gid를 사용자 이름이나 그룹 이름으로 디코딩하는 것을 피 ls -n하지 않습니다 ls -l(이는 비용이 많이 들고 공백이 있는 이름에 문제를 일으킵니다). POSIX는 이러한 필드를 완전히 제거하기 위해 -o/ 옵션을 지정 -g하지만 선택 사항입니다.

의 출력은 ls -nC/POSIX 로케일에서만 지정됩니다. 게다가 파일 경로는 널이 아닌 바이트의 임의 시퀀스이며 C 로케일에서는 텍스트로만 처리할 수 있으므로 LC_ALL=C.

또한 -q파일 이름이나 심볼릭 링크 대상의 줄 바꿈이 문제를 일으키지 않도록 하기 위해 이를 사용합니다.

또한 전체 경로가 에 전달되므로 ls경로 길이가 PATH_MAX 를 초과하면 작동이 중지되므로 임의 깊이의 디렉터리 구조를 처리할 수 없습니다.

버그보고는 꽤 거칠다. 계산된 크기가 null을 반환하는 경우에만 0이 아닌 종료 상태를 보고합니다. 따라서 종료 상태가 0이라고 해서 모든 파일 크기가 고려되었음을 보장하는 것은 아닙니다.

답변2

불행하게도 의 출력 형식은 ls표준화되지 않은 것 같습니다. 따라서 출력을 구문 분석하는 것은 아마도 최선의 아이디어가 아닐 것입니다.

개별 파일의 크기를 바이트 단위로 찾는 또 다른 POSIX 호환 방법은 다음을 사용하는 것입니다 wc -c.

-c각 입력 파일의 바이트 수를 표준 출력에 씁니다.

원천:https://pubs.opengroup.org/onlinepubs/9699919799/utilities/wc.html

$ printf %s 0123456789ABCDEF >sixteenbytestestfile  # example file of 16 bytes length
$ wc -c sixteenbytestestfile
16 sixteenbytestestfile

파일을 인수로 전달하지 않고 표준 입력을 통해 전달하면 파일 이름이 출력에서 ​​생략됩니다.

$ wc -c <sixteenbytestestfile
16

분명히 일부 시스템은 수치 출력 주위에 공백을 추가합니다. 다음을 사용하여 제거할 수 있습니다.산술 확장산술 연산 없이:

$ filesize="   123   "  # possible wc -c output
$ printf %s\\n "-$filesize-"
-   123   -
$ printf %s\\n "-$((filesize))-"
-123-

어쨌든 파일 크기를 가져오는 간단한 함수의 정의는 다음과 같습니다.

$ filesize() { printf %s\\n "$(($(wc -c <"$1")))"; }
$ filesize sixteenbytestestfile
16

관련 정보