0

How can I know how many bytes does it weight the name of a filename? Just the file, not the full path. I've tried this:

echo 'filename.extension' | wc -c

is this right?

1
  • is this right? ... does it give you the correct result?
    – jsotola
    Jan 9, 2022 at 0:28

2 Answers 2

5

Looks fine; echo will however add a trailing newline by default, so echo -n or printf are your friend. If you want to convert /path/to/files/like/this/filename.extension to filename.extension, you'd have something like

filepath='/path/to/files/like/this/filename.extension'
namelength=$(printf "%s" "$(basename "${filepath}")" | wc -c)

If you want character (or something similar) length, Not byte count:
There's a much easier way in POSIX-compatible shells (like bash and zsh, so you're probably using one!):

filename="${filepath##*/}"
namelength=${#filename}

The ${#varname} expansion directly gives you the length of the variable.

6
  • Does ${#var} always return bytes? Here in bash 5.1.12, with a UTF-8 locale active, it seems to count characters and not raw UTF-8 bytes, e.g. var="ąčęėįšųūž"; echo ${#var} returns 9 while printf %s "$var" | wc -c is 18. (I also recall this having changed from 'bytes' to 'characters' somewhere in a minor 5.0.x release and breaking several of my scripts...) Jan 9, 2022 at 10:49
  • @user1686 you raise an interesting point. I was assuming bytes... hm, but my last name in zsh and bash agree with that it's glyphs (maybe?!). Jan 9, 2022 at 11:35
  • 1
    @MarcusMüller, codepoints, most likely. With var=$'a\xcc\x88\xc3\xa4', ${#var} gives 3. That's the two ways to represent the letter ä, so three code points: letter a, combining diaeresis (U+0308), and the a with diaeresis in a single code point (U+00E4). In the C locale, it should give you the number of bytes, e.g. (LC_CTYPE=C; echo ${#var}) prints 5.
    – ilkkachu
    Jan 9, 2022 at 12:10
  • @user1686, oh, and I was on Bash 4.4 still, and it counts code points here. Not sure if some of the 5.0.x has had a slip there, but locales would definitely affect it
    – ilkkachu
    Jan 9, 2022 at 12:14
  • 1
    @ilkkachu: Aha, I went through my Git logs and looks like the actual change wasn't about ${#var} itself, but rather about READLINE_POINT in 5.0 expecting offsets in codepoints rather than bytes. Jan 9, 2022 at 12:19
0

You're not testing a file name, just a string, but what about this, a quick and dirty hack...

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char **argv) {
            int fcount = 1;
            int ret = 0;
            struct stat fstat_details;
    
            while (fcount != argc) {
                    ret = stat (argv[fcount], &fstat_details);
    
                    if (ret == 0) {
                            printf ("file: %s, length: %lu\n", argv[fcount], strlen(argv[fcount]));
                    } else {
                            printf ("file %s not found\n", argv[fcount]);
                    }
                    fcount++;
            }
            return(0);
    }
11
  • When posting C code, it'd be a good idea to post the complete source code, so people don't need to hunt for the header where struct stat is defined in. Not that I'm sure what you'd need stat() for anyway, if all you you need for getting the string length is to call strlen() (which also needs to be declared).
    – ilkkachu
    Jan 9, 2022 at 12:16
  • 1
    How is this C code quick and dirty hack? Jan 9, 2022 at 12:18
  • @ilkkachu, Sorry, misplaced cut'n'paste. The reason for stat, is because the op was concerned about a file name. I assume this file already exists, and this is just a check that they have it correct. Further, I cannot assume what is on the disk, would be the same length as internally in the environment. Everything given is only concerned with vars. At Arkadiusz Drabczyk, because is took me a few minutes and could be made more complete.
    – Bib
    Jan 9, 2022 at 13:53
  • 1
    @Smeterlink, filenames are passed as NUL-terminated strings through the system calls, that is, there's a byte with the numerical value zero as a terminator, not a newline. What the filesystem uses internally might be different, and they might just mark the length separately.
    – ilkkachu
    Jan 10, 2022 at 11:19
  • 1
    @Smeterlink, maybe they are. Maybe they aren't. There's no way to know from userspace, and no reason to care. (Well, unless you're implementing fsck or debugfs.) FWIW, the ext2/3/4 structure for directory entries has an explicit field for the name length (name_len in struct ext4_dir_entry kernel.org/doc/html/latest/filesystems/ext4/…)
    – ilkkachu
    Jan 10, 2022 at 21:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .