Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Given the following ls result:

$ ls
Desktop  Documents  Downloads  Music  Pictures  Public  Templates  Videos

This will give the total number of characters for all files:

$ ls | wc -m
67

But how can I have calculate the number of characters per file name? For the same file list the result I'm after would be something like this:

8
10
10
6
etc...
share|improve this question

3 Answers 3

up vote 3 down vote accepted

This can be done in a very simple shell script:

for file in *; do echo -n "$file" | wc -m; done

Just loop through each file echoing the name to wc. The -n on the echo is so that it doesn't append a newline, which would erroneously increase the count by 1.

share|improve this answer
    
Perfect. Thanks. Also thanks for the echo -n tip. I had noticed the wc was counting one extra character but had not yet started dwelling on that one. –  Fabricio Jan 14 at 1:00

You don't need to call out to wc, bash is perfectly capable: ${#var} is the length of the value of $var.

for f in *; do echo ${#f}; done

reference

share|improve this answer

While @Patrick's answer is perfectly fine if you have to do a similar task over a directory tree's worth of files you'll need to change your tactics slightly. One method for handling this is to use find & while.

find & while

$ depth=2
$ find . -maxdepth $depth -type f -print0 | sed 's|\./||g' | \
    while IFS= read -r -d '' file; do \
      f=$(basename "$file"); printf "%s: %s\n" "$file" "${#f}"; \
    done | column -s : -t
dir2/more files3.txt        15
some long spacey file.txt   25
dir1/more files1.txt        15
dir1/more files2.txt        15
file 1.txt                  10
file 2.txt                  10

The above will generate a list of files separated by \0 (i.e. NULLs). You can use the variable $depth to control how deep find will look. This list is then scrubbed so that any .\ characters are removed via sed.

Lastly we loop through this list and use a printf to print each file's name out along with its length, using Bash's built-in facility to count the length of a string, ${#var}. The printf will print the file + its path but only the size of the file.

The column -s : -t is just to pretty print it. It does so by splitting the output on the colon, :, and then splitting the output up into equidistant columns.

share|improve this answer
    
There's no whitespace problem in Patrick's answer, not even newlines. Since the variable is quoted, there's no issue with horizontal whitespace: var=$'hello\nworld';echo -n "$var" | wc -m => 11 –  glenn jackman Jan 14 at 2:09
    
@glennjackman - what am I missing then? unix.stackexchange.com/questions/9496/…. I know I've switched back and forth on this most annoying topic. I tried his code and you're correct BTW. –  slm Jan 14 at 2:22
1  
The difference is for f in * -- using the wild card avoids word splitting. The shell knows you're iterating over filenames. When you do for f in $(...) you're iterating over words in text output of some program. –  glenn jackman Jan 14 at 11:28
    
@glennjackman - thanks, that's what I kind of figured but a bit more research and re-relearning it I now see the diff. –  slm Jan 14 at 13:08
    
In more detail, I guess the wildcard is expanded into filenames, and those filenames are not subjected to a 2nd round of word-splitting expansion. –  glenn jackman Jan 14 at 14:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.