බාෂ් හි ඇති නාමාවලි හරහා පමණක් මා ලූප කරන්නේ කෙසේද?


296

මට ඩිරෙක්ටරි සහ සමහර ලිපිගොනු සහිත ෆෝල්ඩරයක් ඇත (සමහර ඒවා සඟවා ඇත, තිතෙන් ආරම්භ වේ).

for d in *; do
 echo $d
done

සියලු ලිපිගොනු හරහා ලූප් වනු ඇත, නමුත් මට අවශ්‍ය වන්නේ ඩිරෙක්ටරි හරහා පමණි. මම කොහොමද ඒක කරන්නේ?

Answers:


386

නාමාවලි වලට පමණක් ගැලපෙන පරිදි ඔබට අවසානයේ කප්පාදුවක් නියම කළ හැකිය:

for d in */ ; do
    echo "$d"
done

7
ඩිරෙක්ටරි සඳහා සිම්ලින්ක් ද එයට ඇතුළත් බව සලකන්න.
ස්ටෙෆාන් චසෙලාස්

2
එසේනම් ඔබ සිම්ලින්ක් බැහැර කරන්නේ කෙසේද?
rubo77

4
@ rubo77: [[ -L $d ]]$ d යනු සංකේතාත්මක සබැඳියක් දැයි ඔබට පරීක්ෂා කළ හැකිය .
choroba

1
S අසම්ලැබ්ස් එය වැරදියි, set -Pඩිරෙක්ටරිය වෙනස් කරන විධාන වලට පමණක් බලපායි. sprunge.us/TNac
ක්‍රිස් ඩවුන්

6
ch චෝරෝබා: [[ -L "$f" ]]මෙම නඩුවේදී සිම්ලින්ක්ස් බැහැර නොකරනු ඇත */, ඔබට පසුපස කප්පාදුව ඉවත් කළ යුතුය [[ -L "${f%/}" ]]( පසුපස කප්පාදුව සමඟ සම්බන්ධ වීම සඳහා පරීක්ෂණය බලන්න )
rubo77

87

ඔබට මෙය පරීක්ෂා කළ හැකිය -d:

for f in *; do
    if [ -d "$f" ]; then
        # $f is a directory
    fi
done

මෙය ගොනු පරීක්ෂණ ක්‍රියාකරුවන්ගෙන් එකකි .


9
එය නාමාවලි වලට සමමුහුර්ත ඇතුළත් වන බව සලකන්න.
ස්ටෙෆාන් චසෙලාස්

24
if [[ -d "$f" && ! -L "$f" ]]symlinks බැහැර කරනු ඇත
rubo77

හිස් නාමාවලිය බිඳ දමනු ඇත. if [[ "$f" = "*" ]]; then continue; fi
පිස්ක්වෝර් ගොඩනැගිල්ලෙන් පිටව ගියේ

35

වත්මන් නාමාවලිය තුළ කිසිදු නාමාවලියක් නොමැති නම් චොරොබාගේ විසඳුම අලංකාර වුවත් අනපේක්ෂිත ලෙස හැසිරීමට හැකි බව පරෙස්සම් වන්න. මෙම තත්වය තුළ, forලූපය මඟ හැරීම වෙනුවට , bash dඑක සමාන වූ විට හරියටම ලූපය ධාවනය කරයි */:

#!/usr/bin/env bash

for d in */; do
    # Will print */ if no directories are available
    echo $d
done

මෙම නඩුවෙන් ආරක්ෂා වීමට පහත සඳහන් දෑ භාවිතා කිරීමට මම නිර්දේශ කරමි:

#!/usr/bin/env bash

for f in *; do
    if [ -d ${f} ]; then
        # Will not run if no directories are available
        echo $f
    fi
done

මෙම කේතය වත්මන් නාමාවලියෙහි ඇති සියලුම ලිපිගොනු හරහා ලූප් වනු ඇත, ඩිරෙක්ටරියක් දැයි පරීක්ෂා කරන්න f, ඉන්පසු fතත්වය සත්‍යයක් නම් ප්‍රතිරාවය කරන්න . නම් fකියන්නේ සමාන */, echo $fක්රියාත්මක නොවනු ඇත.


6
වඩා පහසුය shopt -s nullglob.
choroba

24

නාමාවලි පමණක් භාවිතා කරනවාට වඩා විශේෂිත ගොනු තෝරා ගැනීමට ඔබට අවශ්‍ය නම් findඑය වෙත යොමු කරන්න while read:

shopt -s dotglob
find * -prune -type d | while IFS= read -r d; do 
    echo "$d"
done

shopt -u dotglobසැඟවුණු නාමාවලි බැහැර කිරීමට භාවිතා කරන්න (හෝ setopt dotglob/ unsetopt dotglobzsh වලින්).

IFS=$IFSඋදාහරණයක් ලෙස, එකක් අඩංගු ගොනු නාම බෙදීම වළක්වා ගැනීමට :'a b'

බලන්න AsymLabs පිළිතුරු සඳහා පහත සඳහන් findවිකල්ප


සංස්කරණය කරන්න:
ඔබට කාල ලූපය තුළ සිට පිටවීමේ අගයක් නිර්මාණය කිරීමට අවශ්‍ය නම්, ඔබට මෙම උපක්‍රමය මඟින් අමතර උපසිරැසිය මග හැරිය හැක:

while IFS= read -r d; do 
    if [ "$d" == "something" ]; then exit 1; fi
done < <(find * -prune -type d)

2
මම මෙම විසඳුම සොයාගත්තේ: stackoverflow.com/a/8489394/1069083
rubo77

12

ඒ සඳහා ඔබට පිරිසිදු බාෂ් භාවිතා කළ හැකිය, නමුත් සොයා ගැනීම භාවිතා කිරීම වඩා හොඳය:

find . -maxdepth 1 -type d -exec echo {} \;

(අතිරේකව සැඟවුණු නාමාවලි ඇතුළත් වේ)


8
එය නාමාවලි වලට සමමුහුර්ත ඇතුළත් නොවන බව සලකන්න. ඔබට භාවිතා කළ හැකි shopt -s dotglobසඳහා bashසඟවා බහලුම් ඇතුළත් කිරීමට. ඔබගේ ද ඇතුළත් වේ .. -maxdepthඑය සම්මත විකල්පයක් නොවන බව සලකන්න ( -pruneයනු).
ස්ටෙෆාන් චසෙලාස්

2
මෙම dotglobවිකල්පය වැදගත් වන නමුත් dotglobභාවිතය පමණක් අදාළ වේ *. find .සෑම විටම සැඟවුණු නාමාවලි ඇතුළත් වේ (සහ වර්තමාන ඩිර් ද)
rubo77

7

මූල ඩිරෙක්ටරිය හැරුණු විට වර්තමාන වැඩ කරන නාමාවලිය තුළ දෘශ්‍ය හා සැඟවුණු නාමාවලි සොයා ගැනීම සඳහා මෙය සිදු කෙරේ:

නාමාවලි හරහා ලූප් කිරීමට:

 find -path './*' -prune -type d

ප්‍රති result ලයට සිම්ලින්ක් ඇතුළත් කිරීමට:

find -L -path './*' -prune -type d

එක් එක් නාමාවලියට යමක් කිරීමට (සිම්ලින්ක් හැර):

find -path './*' -prune -type d -print0 | xargs -0 <cmds>

සැඟවුණු නාමාවලි බැහැර කිරීමට:

find -path './[^.]*' -prune -type d

ආපසු හරවන ලද අගයන් මත බහු විධාන ක්‍රියාත්මක කිරීමට (ඉතා ව්‍යාකූල උදාහරණයක්):

find -path './[^.]*' -prune -type d -print0 | xargs -0 -I '{}' sh -c \
"printf 'first: %-40s' '{}'; printf 'second: %s\n' '{}'"

'sh -c' වෙනුවට 'bash -c' ආදිය භාවිතා කළ හැකිය.


D සඳහා echo * / 'හි' * / 'in' හි ඩිරෙක්ටරි 60,000 ක් තිබේ නම් කුමක් සිදුවේද?
AsymLabs

ඔබට "ලිපිගොනු ඕනෑවට වඩා" දෝෂයක් ලැබෙනු ඇත, නමුත් එය විසඳිය හැකිය:
ඩෙබියන්

1
Xargs උදාහරණය ක්‍රියා කරන්නේ 9e.g. අවකාශ හෝ නව රේඛා ඇති අය ක්‍රියා නොකරනු ඇත). ... -print0 | xargs -0 ...නිශ්චිත නම් මොනවාදැයි ඔබ නොදන්නේ නම් භාවිතා කිරීමට වඩා හොඳය .
ඇන්තන්

1
සැඟවුණු ලිපිගොනු / නාමාවලි බැහැර කිරීම සහ බහු විධාන ක්‍රියාත්මක කිරීම සඳහා rubo77 එකතු කළ ක්‍රමයක් - ඇත්ත වශයෙන්ම මෙය ස්ක්‍රිප්ට් එකකින් ද කළ හැකිය.
AsymLabs

1
මම, පතුලේ මගේ පිළිතුරු උදාහරණයක් එකතු උත්සවයකට භාවිතා එක් එක් බහලුම වෙත යමක් කිරීමට ආකාරයfind * | while read file; do ...
rubo77

3

සැඟවුණු නාමාවලි (තිතකින් පටන් ගෙන) එක් පේළියකින් සහ බහු විධාන ඇතුළුව ඔබට සියලු ඩිරෙක්ටරි හරහා ලූප කළ හැකිය:

for file in */ .*/ ; do echo "$file is a directory"; done

ඔබට සිම්ලින්ක් බැහැර කිරීමට අවශ්‍ය නම්:

for file in *; do 
  if [[ -d "$file" && ! -L "$file" ]]; then
    echo "$file is a directory"; 
  fi; 
done

සටහන: ලැයිස්තුව භාවිතා */ .*/bash කෘති, පමණක් නොව, ෆෝල්ඩර පෙන්වයි .හා ..zsh එය මෙම පෙන්වන්න නමුත් ෆෝල්ඩරය තුළ කිසිදු සැඟවුණු ගොනු තිබේ නම්, දෝෂයක් විසි නැහැ අතර

සැඟවුණු නාමාවලි ඇතුළත් සහ බැහැර කරන පිරිසිදු අනුවාදයක් ../ dotglob විකල්පය සමඟ වනු ඇත:

shopt -s dotglob
for file in */ ; do echo "$file is a directory"; done

(හෝ setopt dotglobzsh වලින්)

ඔබට ඩොට්ග්ලොබ් සමඟ සැකසිය නොහැක

shopt -u dotglob

3

ලැයිස්තුවේ එක් එක් නාමාවලියෙහි සම්පූර්ණ මාර්ගය මෙයට ඇතුළත් වේ:

for i in $(find $PWD -maxdepth 1 -type d); do echo $i; done

1
අවකාශයන් සහිත ෆෝල්ඩර භාවිතා කරන විට කැඩී යයි
ඇලෙජැන්ඩ්‍රෝ සාසෝ

0

ඩිරෙක්ටරි හරහා ලූප් කිරීමට භාවිතා findකර exec විකල්පයේ ශ්‍රිතයක්-exec අමතන්න :

dosomething () {
  echo "doing something with $1"
}
export -f dosomething
find -path './*' -prune -type d -exec bash -c 'dosomething "$0"' {} \;

සැඟවුණු නාමාවලි භාවිතා කිරීම shopt -s dotglobහෝ shopt -u dotglobඇතුළත් කිරීම / බැහැර කිරීම


0

ලබා දී ඇති මාර්ගයක උප නාමාවලි ගණන සමඟ සියලුම නාමාවලි ලැයිස්තුගත කරයි:

for directory in */ ; do D=$(readlink -f "$directory") ; echo $D = $(find "$D" -mindepth 1 -type d | wc -l) ; done

-1
ls -d */ | while read d
do
        echo $d
done

This is one directory with spaces in the name- නමුත් බහු ලෙස විග්‍රහ කෙරේ.
පිස්ක්වර්

-5
ls -l | grep ^d

හෝ:

ll | grep ^d

ඔබට එය අන්වර්ථයක් ලෙස සැකසිය හැකිය


1
අවාසනාවකට මෙන්, මෙය "මට නාමාවලි හරහා පමණක් ලූප කිරීමට අවශ්‍යය" යන ප්‍රශ්නයට පිළිතුරු සපයනු ඇතැයි මම නොසිතමි - එය නාමාවලි ලැයිස්තුගත කරන මෙම lsපදනම් පිළිතුරට වඩා තරමක් වෙනස් ය .
ජෙෆ් ෂලර්

1
ප්‍රතිදානය විග්‍රහ කිරීම කිසි විටෙකත් හොඳ අදහසක් නොවේ ls: mywiki.wooledge.org/ParsingLs
codeforester
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.