Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

shell - Script fails with spaces in directory names

I have a really easy question, I have found a bunch of similar questions answered but none that solved this for me.

I have a shell script that goes through a directory and prints out the number of files and directories in a sub directory, followed by the directory name.

However it fails with directories with spaces, it attempts to use each word as a new argument. I have tried putting $dir in quotations but that doesn't help. Perhaps because its already in the echo quotations.

for dir in `find . -mindepth 1 -maxdepth 1 -type d`
do
    echo -e "`ls -1 $dir | wc -l`$dir"
done

Thanks in advance for your help :)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Warning: Two of the three code samples below use bashisms. Please take care to use the correct one if you need POSIX sh rather than bash.


Don't do any of those things. If your real problem does involve using find, you can use it like so:

shopt -s nullglob
while IFS='' read -r -d '' dir; do
  files=( "$dir"/* )
  printf '%s%s
' "${#files[@]}" "$dir"
done < <(find . -mindepth 1 -maxdepth 1 -type d -print0)

However, for iterating over only immediate subdirectories, you don't need find at all:

shopt -s nullglob
for dir in */; do
  files=( "$dir"/* )
  printf '%s%s
' "${#files[@]}" "$dir"
done

If you're trying to do this in a way compatible with POSIX sh, you can try the following:

for dir in */; do
  [ "$dir" = "*/" ] && continue
  set -- "$dir"/*
  [ "$#" -eq 1 ] && [ "$1" = "$dir/*" ] && continue
  printf '%s%s
' "$#" "$dir"
done

You shouldn't ever use ls in scripts: http://mywiki.wooledge.org/ParsingLs

You shouldn't ever use for to read lines: http://mywiki.wooledge.org/DontReadLinesWithFor

Use arrays and globs when counting files to do this safely, robustly, and without external commands: http://mywiki.wooledge.org/BashFAQ/004

Always NUL-terminate file lists coming out of find -- otherwise, filenames containing newlines (yes, they're legal in UNIX!) can cause a single name to be read as multiple files, or (in some find versions and usages) your "filename" to not match the real file's name. http://mywiki.wooledge.org/UsingFind


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...