바이트 수를 인간 KiB MiB 등으로 변환하는 표준 도구입니다. 뒤처럼, ls1


94

숫자 값을 1.00과 1023.99 사이로 유지하면서 바이트 수의 정수를 가능한 가장 큰 단위 크기의 사람이 읽을 수있는 카운트로 변환 하는 표준 도구 가 있습니까?

나는 내 자신의 bash / awk 스크립트를 가지고 있지만 많은 / 대부분의 배포판에서 찾을 수 있는 표준 도구를 찾고 있습니다 ... 더 일반적으로 사용 가능한 것이 이상적이며 간단한 명령 줄 인수가 있거나 파이프 입력을 허용 할 수 있습니다.

여기 내가 찾고있는 출력 유형의 예가 있습니다.

    1    Byt  
  173.00 KiB  
   46.57 MiB  
    1.84 GiB  
   29.23 GiB  
  265.72 GiB  
    1.63 TiB  

다음은 bytes-human 스크립트입니다 (위의 출력에 사용됨).

awk -v pfix="$1" -v sfix="$2" 'BEGIN { 
      split( "Byt KiB MiB GiB TiB PiB", unit )
      uix = uct = length( unit )
      for( i=1; i<=uct; i++ ) val[i] = (2**(10*(i-1)))-1
   }{ if( int($1) == 0 ) uix = 1; else while( $1 < val[uix]+1 ) uix--
      num = $1 / (val[uix]+1)
      if( uix==1 ) n = "%5d   "; else n = "%8.2f"
      printf( "%s"n" %s%s\n", pfix, num, unit[uix], sfix ) 
   }'

업데이트 그의 대답에 대한 설명에 설명 된대로 Gilles의 스크립트  의 수정 된 버전이 있습니다 . (내 선호하는 모양에 맞게 수정 됨)

awk 'function human(x) {
         s=" B   KiB MiB GiB TiB EiB PiB YiB ZiB"
         while (x>=1024 && length(s)>1) 
               {x/=1024; s=substr(s,5)}
         s=substr(s,1,4)
         xf=(s==" B  ")?"%5d   ":"%8.2f"
         return sprintf( xf"%s\n", x, s)
      }
      {gsub(/^[0-9]+/, human($1)); print}'

4
그것은 우리가 standard tool만드는 새로운 것 같습니다 :)
Gowtham

@Gowtham-당신의 소원이 이루어질 수 있습니다! 아래 내 답변 또는 blog.frankleonhardt.com/2015/…
FJL

마지막 두 접미사가 바뀌 었습니다. 요타 바이트는 실제로 제타 바이트보다 큽니다.
staticfloat

답변:


89

아니요, 그러한 표준 도구는 없습니다.

비 임베디드 Linux 및 Cygwin에서 GNU coreutils 8.21 (2013 년 2 월, 아직 모든 배포판에 존재하지는 않음) 이후로를 사용할 수 있습니다 numfmt. 정확히 동일한 출력 형식을 생성하지는 않습니다 (coreutils 8.23부터 소수점 다음에 두 자리 숫자를 얻을 수 있다고 생각하지 않습니다).

$ numfmt --to=iec-i --suffix=B --padding=7 1 177152 48832200 1975684956
     1B
 173KiB
  47MiB
 1.9GiB

이전의 많은 GNU 도구는이 형식을 생성 할 수 있으며 GNU 정렬은 coreutils 7.5 (2009 년 8 월부터 현대의 내장되지 않은 Linux 배포판에 존재) 이후의 단위로 숫자를 정렬 할 수 있습니다 .


코드가 약간 복잡하다는 것을 알았습니다. 더 깨끗한 awk 버전이 있습니다 (출력 형식이 정확히 동일하지는 않습니다)

awk '
    function human(x) {
        if (x<1000) {return x} else {x/=1024}
        s="kMGTEPZY";
        while (x>=1000 && length(s)>1)
            {x/=1024; s=substr(s,2)}
        return int(x+0.5) substr(s,1,1)
    }
    {sub(/^[0-9]+/, human($1)); print}'

( 보다 전문적인 질문에서 다시 게시 됨 )


괜찮 감사. 당신의 스크립트에 대해, 나는 기본적으로 그것을 정말로 좋아합니다. 내주의를 끌었던 몇 가지 사항이 있습니다. (1) var s이 (가) 주도해야합니다 B. 또한이 문자열은 IEC 이진 표기법으로 쉽게 변경됩니다. (2) 1 <다음 크기> (쉽게 변경됨) 에 찬성 하여 1000-1023 범위를 건너 뜁니다 (3) 십진수 값이 없습니다 (원하는). 다시 이것은 쉽게 변경됩니다. 소수점 이하 두 자리를 표시 할 때 형식은 값 1019-1023의 경우 <다음 크기>가됩니다 . 그러나 해결 방법은 가치가 없습니다. 일반적인 참조를 위해 내 답변에 수정 된 버전을 게시했습니다. %fround-up
Peter.O

coreutils를 사용하는 osx homebrew 사용자를위한 gnumfmt
verboze

변환하고자하는 사람들을 위해 du사람이 읽을 수있는 형식으로 번호를 추가해야 할 수도 있습니다 --block-size=1du명령.
pawamoy

68

v. 기준 8.21으로 다음이 coreutils포함됩니다 numfmt.

numfmt다양한 표현으로 숫자를 읽고 요청에 따라 숫자를 다시 포맷합니다.
가장 일반적인 사용법은 숫자를 사람의 표현 으로 또는 사람의 표현으로 변환 하는 것입니다.

예 :

printf %s\\n 5607598768908 | numfmt --to=iec-i
5.2Ti

다양한 다른 예 (필터링, 입 / 출력 처리 등 포함)가 여기 에 제시 됩니다.


또한, 현재의 coreutils브이. 8.24, numfmt유사한 필드 범위 사양 여러 필드를 처리 수 cut와 함께 출력 정밀도 설정을 지원 --format옵션

numfmt --to=iec-i --field=2,4 --format='%.3f' <<<'tx: 180000 rx: 2000000'
tx : 175.782Ki rx : 1.908Mi

numfmt는 coreutils-8.21부터 coreutils 패키지에 새로 추가 된 도구입니다.
Zama Ques

1
이것은 이제 받아 들여질 것입니다.
Andy Foster

23

다음은 bash 전용 옵션이며, bc내장 또는 비 내장, 10 진수 형식 및 이진 단위입니다.

bytesToHuman() {
    b=${1:-0}; d=''; s=0; S=(Bytes {K,M,G,T,P,E,Z,Y}iB)
    while ((b > 1024)); do
        d="$(printf ".%02d" $((b % 1024 * 100 / 1024)))"
        b=$((b / 1024))
        let s++
    done
    echo "$b$d ${S[$s]}"
}

예 :

$ bytesToHuman 123456789
117.73 MiB

$ bytesToHuman 1000000000000 # "1TB of storage"
931.32 GiB                   #  1TB of storage

$ bytesToHuman 
0 Bytes

MASHGit의 Bash for Windows를 포함하여 모든 Bash 버전에서 잘 수행되어야합니다.


이것은 내 bash 요구에 가장 적합한 대답입니다. 안타깝게도 영업일 이후 1/2 년이 지나면 투표 목록을 올리는 데 시간이 걸릴 수 있습니다.
WinEunuuchs2Unix

@ WinEunuuchs2Unix 감사합니다, 그것이 당신에게 도움이되어서 기쁩니다 :)
Camilo Martin

마지막 두 접미사가 바뀌 었습니다. 요타 바이트는 실제로 제타 바이트보다 큽니다.
staticfloat

6

Peter.O의 수정 된 Gilles의 awk 스크립트에서 영감을 얻은 완전한 재 작성입니다.

변경 사항 :

  • Peter.O의 버그를 수정하여> 1자를 초과하는 문자열> 1자를 찾으십시오. 그 버그로 인해 그의 코드는 ZiB 장치에서 작동하지 않습니다.
  • 긴 문자열로 구분 된 단위 크기의 매우 못생긴 하드 코딩을 제거합니다.
  • 패딩을 활성화 / 비활성화하는 명령 줄 스위치를 추가합니다.
  • base-1024 (KiB)에서 base-1000 (KB) 표기법으로 이동하는 명령 행 스위치를 추가합니다.
  • 사용하기 쉬운 기능으로 모두 포장합니다.
  • 나는 이것을 공개 도메인에 배치하고 널리 사용되는 것을 환영합니다.

암호:

bytestohuman() {
    # converts a byte count to a human readable format in IEC binary notation (base-1024), rounded to two decimal places for anything larger than a byte. switchable to padded format and base-1000 if desired.
    local L_BYTES="${1:-0}"
    local L_PAD="${2:-no}"
    local L_BASE="${3:-1024}"
    BYTESTOHUMAN_RESULT=$(awk -v bytes="${L_BYTES}" -v pad="${L_PAD}" -v base="${L_BASE}" 'function human(x, pad, base) {
         if(base!=1024)base=1000
         basesuf=(base==1024)?"iB":"B"

         s="BKMGTEPYZ"
         while (x>=base && length(s)>1)
               {x/=base; s=substr(s,2)}
         s=substr(s,1,1)

         xf=(pad=="yes") ? ((s=="B")?"%5d   ":"%8.2f") : ((s=="B")?"%d":"%.2f")
         s=(s!="B") ? (s basesuf) : ((pad=="no") ? s : ((basesuf=="iB")?(s "  "):(s " ")))

         return sprintf( (xf " %s\n"), x, s)
      }
      BEGIN{print human(bytes, pad, base)}')
    return $?
}

테스트 사례 (출력을 보려는 경우) :

bytestohuman 1; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 500; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1023; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1024; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1500; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000000; echo "${BYTESTOHUMAN_RESULT}.";

bytestohuman 1 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 500 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1023 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1024 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1500 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";

bytestohuman 1 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 500 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1023 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1024 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1500 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000000 yes; echo "${BYTESTOHUMAN_RESULT}.";

bytestohuman 1 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 500 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1023 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1024 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1500 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";

즐겨!


5

perlCPAN 에는 몇 가지 모듈 이 있습니다 : Format :: Human :: BytesNumber :: Bytes :: Human , 후자는 좀 더 완벽합니다.

$ echo 100 1000 100000 100000000 |
  perl -M'Number::Bytes::Human format_bytes' -pe 's/\d{3,}/format_bytes($&)/ge'
100 1000 98K 96M

$ echo 100 1000 100000 100000000 |
  perl -M'Number::Bytes::Human format_bytes' -pe 's/\d{3,}/
   format_bytes($&,bs=>1000, round_style => 'round', precision => 2)/ge'
100 1.00k 100k 100M

그리고 그 반대의 경우 :

$ echo 100 1.00k 100K 100M 1Z |
  perl -M'Number::Bytes::Human parse_bytes' -pe '
    s/[\d.]+[kKMGTPEZY]/parse_bytes($&)/ge'
100 1024 102400 104857600 1.18059162071741e+21

참고 : 이 기능 parse_bytes()버전 0.09 (2013-03-01)추가되었습니다.


5

리눅스를 통해 -바이트 계산을위한 명령 줄 계산기가 있습니까? -스택 오버플로 , 나는 GNU 유닛 에 대해 발견했다. 그러나 SO 페이지에는 예제가 없다. 여기에 표시되지 않았으므로 여기에 대한 작은 메모가 있습니다.

먼저 장치가 있는지 확인하십시오.

$ units --check-verbose |grep byte
doing 'byte'

$ units --check-verbose |grep mega
doing 'megalerg'
doing 'mega'

$ units --check-verbose |grep mebi
doing 'mebi'

그것들이 주어지면 변환을 수행하십시오- printf형식 지정자는 숫자 결과의 형식을 지정하도록 허용됩니다.

$ units --one-line -o "%.15g" '20023450 bytes' 'megabytes'  # also --terse
    * 20.02345
$ units --one-line -o "%.15g" '20023450 bytes' 'mebibytes' 
    * 19.0958499908447
$ units --one-line -o "%.5g" '20023450 bytes' 'mebibytes' 
    * 19.096

3

실제로, 정확히이 작업을 수행하는 유틸리티가 있습니다. 나는 그것을 쓸 줄 알았는데. * BSD 용으로 작성되었지만 BSD 라이브러리가있는 경우 Linux에서 컴파일해야합니다 (일반적으로 생각합니다).

방금 새 버전을 출시했으며 여기에 게시되었습니다.

http://blog.frankleonhardt.com/2015/freebsd-hr-utility-human-readable-number-filter-man-page/

그것은 hr이라고 불리며 stdin (또는 파일)을 취하고 숫자를 사람이 읽을 수있는 형식으로 변환합니다 (현재) ls -h와 정확히 같은 방식으로 개별 피드를 행, 스케일로 선택할 수 있습니다 사전 스케일 된 단위 (예 : 512 바이트 블록 인 경우 Mb 등으로 변환), 열 패딩 등을 조정합니다.

몇 년 전 필자는 쉘 스크립트를 작성하려고 시도하는 것이 지적 적으로 흥미롭지 만 완전히 광기라고 생각했기 때문에 그것을 썼습니다.

예를 들어 hr을 사용하면 다음과 같이 정렬 된 디렉토리 크기 목록을 쉽게 얻을 수 있습니다 (1Kb 단위로 나오고 변환하기 전에 이동해야 함).

뒤 -d1 | 정렬 -n | hr -sk

du는 -h 출력을 생성하지만 sort는 정렬하지 않습니다. 기존 유틸리티에 -h를 추가하는 것은 유닉스 철학을 따르지 않는 전형적인 사례입니다. 정의 된 작업을 실제로 수행하는 간단한 유틸리티가 있습니다.


2

다음은 bash에서 거의 순전히 수행하는 방법입니다. 부동 소수점 수학에는 'bc'만 있으면됩니다.

function bytesToHR() {
        local SIZE=$1
        local UNITS="B KiB MiB GiB TiB PiB"
        for F in $UNITS; do
                local UNIT=$F
                test ${SIZE%.*} -lt 1024 && break;
                SIZE=$(echo "$SIZE / 1024" | bc -l)
        done

    if [ "$UNIT" == "B" ]; then
        printf "%4.0f    %s\n" $SIZE $UNIT
    else
        printf "%7.02f %s\n" $SIZE $UNIT
    fi
}

용법:

bytesToHR 1
bytesToHR 1023
bytesToHR 1024
bytesToHR 12345
bytesToHR 123456
bytesToHR 1234567
bytesToHR 12345678

산출:

   1    B
1023    B
   1.00 KiB
  12.06 KiB
 120.56 KiB
   1.18 MiB
  11.77 MiB

1
user@host:/usr$ alias duh="du -s -B1 * | sort -g | numfmt --to=iec-i --format='%10f'"
user@host:/usr$ duh

제공합니다 :

 4.0Ki games
 3.9Mi local
  18Mi include
  20Mi sbin
 145Mi bin
 215Mi share
 325Mi src
 538Mi lib

불행히도 소수점 이하 두 자릿수를 얻는 방법을 알 수 없습니다. 우분투 14.04에서 테스트되었습니다.


1

@ don_crissti의 첫 번째 대답은 좋지만, 사용도 짧아 질 수 있습니다 문자열 여기에 , 예를

$ numfmt --to=iec-i <<< "12345"
13Ki

$ numfmt --to=iec-i --suffix=B <<< "1234567"
1.2MiB

또는

$ numfmt --from=iec-i --to=iec-i --suffix=B <<< "12345Ki"
13MiB

경우 <<<사용할 수 없습니다 당신은 예를 사용할 수 있습니다

$ echo "1234567" | numfmt --to=iec-i --suffix=B
1.2MiB

1

파이썬 도구 존재

$pip install humanfriendly  # Also available as a --user install in ~/.local/bin

$humanfriendly --format-size=2048
2.05 KB
$humanfriendly --format-number=2048
2,048

--binary 플래그가 표시되지 않습니다 :( 따라서 바이너리 표현을 위해 파이썬을 직접 사용해야합니다.

$python -c 'import sys, humanfriendly; print(humanfriendly.format_size(int(sys.argv[1]), binary=True))' 2048
2 KiB
$python -c 'import sys, humanfriendly; print(humanfriendly.format_size(int(sys.argv[1]), binary=True))' 2000
1.95 KiB

1

나는 같은 문제가 있었고 awklog()함수를 사용하여 간단한 해결책을 신속하게 생각해 냈습니다 .

awk '
  BEGIN {
    split("B,kiB,MiB,GiB", suff, ",")
  }

  {
    size=$1;
    rank=int(log(size)/log(1024));
    printf "%.4g%s\n", size/(1024**rank), suff[rank+1]
  }
'

그리고 부동 소수점을 사용할 때 손실되는 정밀도는 그 정밀도가 어쨌든 손실되기 때문에 나쁘지 않습니다.


0

귀하의 질문에 대한 답변은 예입니다.

출력 형식이 정확히 사양에 맞지는 않지만 변환 자체는 매우 표준적인 도구 (또는 두 개) 로 쉽게 수행됩니다 . 내가 참조하는 것은 dcbc입니다. 출력을 변경하여 세그먼트 화 된 보고서를 얻을 수 있습니다. 이처럼 :

{   echo 1024 o           #set dc's output radix
    echo 1023 pc          #echo a number then print + clear commands
    echo 1024 pc
    echo 1025 pc
    echo 8000000 pc
} | dc

... 인쇄 ...

 1023                    #1 field 1023 bytes
 0001 0000               #2 fields 1k 0b
 0001 0001               #2 fields 1k 1b
 0007 0644 0512          #3 fields 7m 644k 512b or 7.64m

dc개인적으로 가장 좋아하기 때문에 위와 같이 사용 하지만 bc다른 구문으로 동일하게 수행 할 수 있으며 POSIX에서 지정한 것과 동일한 형식 규칙을 준수합니다.

  • bc obase

    • 16보다 큰 염기의 경우, 각 숫자는 별도의 여러 자리 10 진수로 작성됩니다. 최상위 소수 자릿수를 제외한 각 숫자 앞에는 단일 공백이 있어야합니다 . 17에서 100까지의 밑줄에는 bc두 자리 십진수를 써야합니다. 101부터 1000까지의 밑, 3 자리 10 진수 문자열 등. 예를 들어, 밑 25의 10 진수 1024는 다음과 같이 작성됩니다.

    01 15 24

    기본 125에서

    008 024


-1

짧고 달콤한 껍질 전용 솔루션 :

convertB_human() {
NUMBER=$1
for DESIG in Bytes KB MB GB TB PB
do
   [ $NUMBER -lt 1024 ] && break
   let NUMBER=$NUMBER/1024
done
printf "%d %s\n" $NUMBER $DESIG
}

십진수 물약은 표시되지 않습니다.

let VAR=expression콘 틱입니다. 로 대체 VAR=$(( expression ))거듭난 틱합니다.


이 솔루션은 / 1024가 항상 반올림되므로 많은 오류가 발생합니다. 1.5 TiB를 2 TiB로 반올림하지 않을 것이라고 확신합니다.
Geoffrey

-2

AFAIK에는 텍스트를 전달할 수있는 표준 도구가 없으며 사람이 읽을 수있는 양식을 반환합니다. 배포판에 대해 상기 작업을 수행하기위한 패키지를 찾을 수 있습니다.

그러나 왜 그런 도구가 필요한지 이해하지 못합니다. 관련 출력을 제공하는 대부분의 패키지에는 일반적으로 사람이 읽을 수있는 출력을위한 -h 또는 동등한 스위치가 있습니다.


1
이해의 목적으로 : 사람이 읽을 수있는 것은 바로 그 의미입니다. 인간이 읽을 수 있습니다. 언급 한 도구로 표시되는 다양한 크기 의 단위는 단위의 균일 성이 필수적인 프로그래밍 계산 용이 아닙니다. 항상 정수 인 바이트로 작업하는 것이 bash 가 산술을 수행 할 수 있는 유일한 방법 입니다. 따라서 ... 바이트로 계산합니다 ... 예를 들어 Human으로 보고하십시오 . "총
2.44GiB의

나는 이것이 당신의 질문의 일부라고 생각합니다. 문제가 해결 된 것 같습니다. 행운을 빕니다.
shellter

1
일반적인 응용 프로그램은 정렬 할 바이트 수를 생성하고 정렬 후 사람이 읽을 수있는 단위로 변환하는 것입니다.
Gilles
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.