sh - What is the meaning of ${arg##/*/} and {} \; in shell scripting -
please find code below displaying directories in current folder.
- what meaning of
${arg##/*/}in shell scripting. (botharg#*,arg##/*/gives same output. ) - what meaning of
{} \;in loop statement.
for arg in `find . -type d -exec ls -d {} \;` echo "output 1" ${arg##/*/} echo "output 2" ${arg#*} done
adding @joso's helpful answer:
${arg#*} fundamentally pointless expansion, result identical $arg itself, since strips shortest prefix matching any character (*) , shortest prefix matching character empty string.
${arg##/*/} - stripping longest prefix matching pattern /*/ - useless in context, because output paths ./-prefixed due use of find ., there no prefix starting /. contrast, ${arg##*/} work , strip parent path (leaving folder-name component only).
aside being ill-advised parse command output in for loop, @joso points out, find command in op overly complicated , inefficient (as aside, clarify, find command lists folders in current folder's subtree, not immediate subfolders):
find . -type d -exec ls -d {} \; can simplified to:
find . -type d the 2 commands same: -exec ls -d {} \; find default anyway (an implied -print).
if put together, get:
find . -mindepth 1 -type d | while read -r arg echo "folder name: ${arg##*/}" echo "parent path: ${arg%/*}" done note i've used ${arg%/*} second output item, strips shortest suffix matching /* , returns parent path; furthermore, i've added -mindepth 1 find doesn't match .
@joso, in comment, demonstrates solution that's both simpler , more efficient; uses -exec process shell command in-line , + pass many paths possible @ once:
find . -mindepth 1 -type d -exec /bin/sh -c \ 'for arg; echo "folder name: ${arg##*/}"; echo "parent: ${arg%/*}"; done' \ -- {} + finally, if have gnu find, things easier, can take advantage of -printf primary, supports placeholders things filenames , parent paths:
find . -type d -printf 'folder name: %f\nparen path: %h\n' here's bash-only solution based on globbing (pathname expansion), courtesy of @adrian frühwirth:
caveat: requires bash 4+, shell option globstar turned on (shopt -s globstar) - off default.
shopt -s globstar # bash 4+ only: turn on support ** arg in **/ # process directories in entire subtree echo "folder name: $(basename "$arg")" echo "parent path: $(dirname "$arg")" done note i'm using basename , dirname here parsing, conveniently ignore terminating / glob **/ invariably adds matches.
afterthought re processing find's output in while loop: on off chance filenames contain embedded \n chars, can parse follows, using null char. separate items (see comments why -d $'\0' rather -d '' used):
find . -type d -print0 | while read -d $'\0' -r arg; ...
Comments
Post a Comment