Bash 스크립트에서 파일 크기를 얻는 방법은 무엇입니까?

Bash 스크립트에서 파일 크기를 얻는 방법은 무엇입니까?

Bash 스크립트에서 파일 크기를 얻는 방법은 무엇입니까?

나중에 사용하기 위해 bash 변수에 어떻게 할당합니까?

답변1

GNU 시스템의 경우 가장 좋은 옵션은 다음과 같습니다.

stat --printf="%s" file.any

~에서사람들 통계:

%s 총 크기(바이트)

Bash 스크립트에서:

#!/bin/bash
FILENAME=/home/heiko/dummy/packages.txt
FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."

참고: 참조@chbrown의 답변statBSD 또는 macOS 시스템에서 사용하는 방법을 알아보세요 .

답변2

file_size_kb=`du -k "$filename" | cut -f1`

이를 사용할 때의 문제점 stat은 GNU(Linux) 확장이라는 것입니다. du -k그리고cut -f1POSIX에 의해 지정되므로 모든 Unix 시스템에 이식 가능합니다.

예를 들어, Solaris에는 bash가 함께 제공되지만 stat.따라서 이것이 전적으로 가정은 아닙니다.

ls출력의 정확한 형식이 지정되지 않아 출력을 이식 가능하게 구문 분석할 수 없는 유사한 문제가 있습니다. du -h또한 GNU 확장입니다.

가능할 때마다 이동식 구조물을 고수하면 미래에 사람들의 삶을 더 쉽게 만들 수 있습니다. 어쩌면 당신 자신의 것일 수도 있습니다.

답변3

단어 개수 명령( )을 사용할 수도 있습니다 wc.

wc -c "$filename" | awk '{print $1}'

문제는 wc파일 이름을 추가하고 출력을 들여쓰기한다는 것입니다. 예를 들어:

$ wc -c somefile.txt
    1160 somefile.txt

단지 파일 크기 계산을 위해 전체 해석 언어 또는 스트림 편집기를 연결하지 않으려면 wc파일 이름이 표시되지 않도록 파일에서 입력을 리디렉션하면 됩니다.

wc -c < "$filename"

언급한 대로 마지막 형식을 명령 대체와 함께 사용하여 찾고 있는 쉘 변수 값을 쉽게 얻을 수 있습니다.자일스다음과 같은.

size="$(wc -c <"$filename")"

답변4

당신이 무엇을 의미하는지에 따라 달라집니다크기.

size=$(wc -c < "$file")

파일에서 읽을 수 있는 바이트 수를 알려줍니다. IOW, 파일 내용의 크기입니다. 그러나 파일의 내용을 읽습니다(파일이 일반 파일이거나 wc대부분의 구현에서 최적화로서 일반 파일을 가리키는 심볼릭 링크가 아닌 경우). 부작용이 있을 수 있습니다. 예를 들어 명명된 파이프의 경우 읽은 내용을 더 이상 읽을 수 없으며, 또는 크기가 무한한 경우 /dev/zero에는 시간이 걸립니다. 이는 또한 파일에 대한 권한이 /dev/random필요하다는 것을 의미합니다 .read마지막 액세스 타임스탬프파일 내용이 업데이트될 수 있습니다.

이는 표준적이고 이식 가능하지만 일부 wc구현에서는 이 출력에 선행 공백이 포함될 수 있습니다. 이를 제거하는 한 가지 방법은 다음을 사용하는 것입니다.

size=$(($(wc -c < "$file")))

또는 출력이 생성 되지 않을 때 dash( 예: 파일을 열 수 없는 경우) 빈 산술 표현식에 대한 오류를 피하세요 .yashwc

size=$(($(wc -c < "$file") +0))

ksh93내장 된 wc기능(활성화한 것처럼 호출할 수도 있음 command /opt/ast/bin/wc)이 있어 이 셸의 일반 파일에 가장 효과적입니다.

stat다양한 시스템에는 시스템 호출에 대한 인터페이스 인 이라는 명령이 있습니다 .stat()lstat()

이는 인덱스 노드에서 발견된 정보를 보고합니다. 정보 중 하나가 st_size속성입니다. 일반 파일의 경우 이는 콘텐츠의 크기(오류 없이 읽을 수 있는 데이터의 양( wc -c대부분의 구현에서 최적화에 사용하는 것))입니다. 기호 링크의 경우 대상 경로의 크기(바이트)입니다. 명명된 파이프의 경우 시스템에 따라 이 값은 0이거나 파이프 버퍼의 현재 바이트 수일 수 있습니다. 블록 장치의 경우에도 마찬가지입니다. 시스템에 따라 0 또는 기본 저장소의 바이트 크기가 결정됩니다.

이 정보를 얻기 위해 파일에 대한 읽기 권한이 필요하지 않으며 링크된 디렉터리에 대한 검색 권한만 있으면 됩니다.

시간순으로 보면 다음과 같습니다.

  • 아이릭스stat(90년대):

    stat -qLs -- "$file"
    

    st_size( )의 속성을 반환 하거나 다음을 수행합니다.$filelstat()

    stat -s -- "$file"
    

    동일합니다. 단, 심볼릭 링크인 경우는 제외됩니다 $file. 이 경우 st_size심볼릭 링크의 확인된 파일입니다.

  • zsh stat내장(현재 라고도 함 zstat) 모듈 zsh/stat(로드 중 zmodload zsh/stat)(1997):

    stat -L +size -- $file # st_size of file
    stat +size -- $file    # after symlink resolution
    

    또는 변수에 저장합니다.

    stat -L -A size +size -- $file
    

    분명히 이것은 껍질 중 가장 효율적입니다.

  • 암소 비슷한 일종의 영양stat(2001); 2005년부터 BusyBox에, 2013년부터 statToybox에 포함되었습니다 stat(둘 다 GNU stat인터페이스를 복사함).

    stat -c %s -- "$file"  # st_size of file
    stat -Lc %s -- "$file" # after symlink resolution
    

    -L( IRIX나 와는 반대의 의미이니 주의하시기 바랍니다 zsh stat.)

  • BSDstat(2002):

    stat -f %z -- "$file"  # st_size of file
    stat -Lf %z -- "$file" # after symlink resolution
    

stat()또는 일부 스크립팅 언어의 /features를 사용할 수도 있습니다 . 예를 들면 다음과 같습니다.lstat()perl

perl -le 'print((lstat shift)[7])' -- "$file"

AIX에도 하나가 있습니다istat주문하다stat()모든 정보 (Symlink가 아니므 로 심볼릭 링크에 적용할 수 없음)를 덤프하며 lstat()이 정보를 후처리에 사용할 수 있습니다. 예를 들면 다음과 같습니다.

LC_ALL=C istat "$file" | awk 'NR == 4 {print $5}'

(@JeffSchaller에게 감사드립니다.세부정보를 파악하는 데 도움을 주세요.).

존재하다 tcsh:

@ size = -Z $file:q

(해결 후 심볼릭 링크의 크기)

GNU가 명령을 도입하기 훨씬 전에 statGNU 명령과 그 조건자를 사용하여 동일한 효과를 얻을 수 있었습니다(1991년):find-printf

find -- "$file" -prune -printf '%s\n'    # st_size of file
find -L -- "$file" -prune -printf '%s\n' # after symlink resolution

$file-하지만 한 가지 문제는 이 메서드가 or로 시작 하면 작동하지 않는다는 것입니다 find(예 !: (...).

버전 4.9부터 이 문제는 인수 대신 stdin을 통해 파일 경로를 전달하여 해결할 수 있습니다.

printf '%s\0' "$file" |
  find -files0-from - -prune -printf '%s\n'

stat()/ lstat()정보를 가져오는 표준 명령은 입니다 ls.

POSIXly에서는 다음과 같이 할 수 있습니다.

LC_ALL=C ls -dln -- "$file" | awk '{print $5; exit}'

( 후자가 필요하지 않도록 -n힌트가 필요 하지만 일부 BSD에서는 필요하다는 것을 알 수 있습니다.)-l

그리고 -L심볼릭 링크 확인 후에 동일한 내용을 추가하세요. 다섯 번째 필드 는 크기가 아닌 장치 주요 번호이지만 이는 장치 파일에는 적용되지 않습니다 .

블록 장치의 경우 stat()0을 반환하는 시스템에는 st_size일반적으로 블록 장치의 크기를 보고하는 다른 API가 있습니다. 예를 들어 Linux에는 이를 사용하는 명령이 있으며 BLKGETSIZE64 ioctl()현재 대부분의 Linux 배포판에는 다음과 같은 명령이 제공됩니다 .blockdev

blockdev --getsize64 -- "$device_file"

그러나 이 장치 파일에 대한 읽기 권한이 필요합니다. 차원은 종종 다른 방법으로 파생될 수 있습니다. 예를 들어(여전히 Linux에서는):

lsblk -bdno size -- "$device_file"

빈 장치를 제외하고는 작동합니다.

모두에게 적합한 하나의 접근 방식탐색 가능한파일(일반 파일, 대부분의 블록 장치 및 일부 문자 장치 포함)에 대해 이를 수행하는 방법은 파일을 열고 끝을 확인하는 것입니다.

  • 사용 zsh( zsh/system모듈을 로드한 후):

    {sysseek -w end 0 && size=$((systell(0)))} < $file
    
  • 그리고 ksh93:

    < "$file" <#((size=EOF))
    

    또는

    { size=$(<#((EOF))); } < "$file"
    
  • 그리고 perl:

    perl -le 'seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN' < "$file"
    

명명된 파이프를 사용하면 일부 시스템(적어도 AIX, Solaris, HP/UX)에서 파이프 버퍼의 데이터 양을 stat()s에서 사용할 수 있게 만드는 것을 확인했습니다 st_size. 일부(Linux 또는 FreeBSD와 같은)는 그렇지 않습니다.

적어도 Linux에서는 FIONREAD ioctl()파이프를 연 후에 사용할 수 있습니다(멈춤을 방지하기 위해 읽기+쓰기 모드에서).

fuser -s -- "$fifo_file" && 
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &FIONREAD, $n) or die$!;
            print unpack "L", $n' <> "$fifo_file"

하지만 그렇지 않은 동안 참고하세요읽다파이프의 내용, 여기서 명명된 파이프를 여는 것만으로도 여전히 부작용이 있습니다. fuser특정 프로세스에 열린 파이프가 있는지 먼저 확인하여 이 문제를 완화하지만 모든 프로세스를 확인하는 것이 불가능할 수 있으므로 이것이 완벽하지는 않습니다 fuser.

이제 지금까지 우리는 단지 고려했습니다기초적인파일과 관련된 데이터입니다. 이는 메타데이터의 크기와 해당 파일을 저장하는 데 필요한 모든 지원 인프라를 고려하지 않습니다.

반환된 또 다른 inode 속성 stat()은 입니다 st_blocks. 이는 512바이트(HP/UX의 1024) 파일 데이터(때때로 Linux의 ext4 파일 시스템의 확장 속성과 같은 일부 메타데이터)를 저장하는 데 사용되는 블록입니다. 여기에는 inode 자체는 포함되지 않으며 파일이 링크된 디렉터리의 항목도 포함되지 않습니다.

압축, 희소성(때때로 일부 메타데이터), 추가 인프라(예: 일부 파일 시스템의 간접 블록)가 후자에 영향을 미칠 수 있으므로 크기와 디스크 사용량은 반드시 밀접한 관련이 있는 것은 아닙니다.

이는 일반적 du으로 디스크 사용량을 보고하는 데 사용됩니다. 위에 나열된 대부분의 명령은 이 정보를 제공합니다.

  • POSIXLY_CORRECT=1 ls -sd -- "$file" | awk '{print $1; exit}'
  • POSIXLY_CORRECT=1 du -s -- "$file"(파일의 디스크 사용량이 포함된 디렉터리에는 적용되지 않습니다.)
  • 암소 비슷한 일종의 영양find -- "$file" -printf '%b\n'
  • zstat -L +block -- $file
  • 암소 비슷한 일종의 영양stat -c %b -- "$file"
  • BSDstat -f %b -- "$file"
  • perl -le 'print((lstat shift)[12])' -- "$file"

엄밀히 말하면 1970년대 초반의 UNIX 버전 v1부터 v4까지에는 하나의 stat명령이 있었습니다. 단지 inode에서 정보를 덤프하고 옵션은 사용하지 않습니다. v5(1974)에서는 사라진 것으로 보입니다. 아마도 ls -l.

관련 정보