Open Group 사양에 따르면 POSIX는du
-b
크기를 바이트 단위로 표시하는 옵션 은 없습니다 . 그렇다면 파일이나 폴더의 크기를 바이트 단위로 가져오는 POSIX 호환 방법은 무엇입니까?
답변1
du
GNU가 수행하는 작업을 대략적으로 설명 -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 ./-print
find
/
--
ls
우리는 uid/gid를 사용자 이름이나 그룹 이름으로 디코딩하는 것을 피 ls -n
하지 않습니다 ls -l
(이는 비용이 많이 들고 공백이 있는 이름에 문제를 일으킵니다). POSIX는 이러한 필드를 완전히 제거하기 위해 -o
/ 옵션을 지정 -g
하지만 선택 사항입니다.
의 출력은 ls -n
C/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