태그 보관물: text-processing

text-processing

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

숫자 값을 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}'



답변

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

비 임베디드 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}'

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


답변

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


답변

다음은 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 버전에서 잘 수행되어야합니다.


답변

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}.";

즐겨!


답변

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)추가되었습니다.


답변

리눅스를 통해 -바이트 계산을위한 명령 줄 계산기가 있습니까? -스택 오버플로 , 나는 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


답변

실제로, 정확히이 작업을 수행하는 유틸리티가 있습니다. 나는 그것을 쓸 줄 알았는데. * 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를 추가하는 것은 유닉스 철학을 따르지 않는 전형적인 사례입니다. 정의 된 작업을 실제로 수행하는 간단한 유틸리티가 있습니다.