සොයාගැනීමේ ප්‍රතිදානය නරක අතට හැරෙන්නේ ඇයි?


178

මෙම ප්රශ්නය දේවානුභාවයෙන්

පෙළ සැකසීමට ෂෙල් ලූපයක් භාවිතා කිරීම නරක පුරුද්දක් ලෙස සලකන්නේ ඇයි?

මෙම ඉදිකිරීම් මම දකිමි

for file in `find . -type f -name ...`; do smth with ${file}; done

හා

for dir in $(find . -type d -name ...); do smth with ${dir}; done

මෙවැනි දේ වළක්වා ගත යුත්තේ ඇයිද යන්න පැහැදිලි කරමින් සමහර අය එම සටහන් වලට අදහස් දැක්වීමට කාලය ගත කළත් දිනපතාම පාහේ මෙහි භාවිතා කිරීම ...
එවැනි තනතුරු ගණන දැකීම (සහ සමහර විට එම අදහස් සරලව නොසලකා හැරීම) මම හිතුවා මටත් ප්‍රශ්නයක් අහන්න පුළුවන් කියලා:

findනිමැවුමේ නිමැවුම නරක පුරුද්දක් වන්නේ ඇයි සහ එක් එක් ගොනුවේ නම / මාර්ගය සඳහා විධාන එකක් හෝ කිහිපයක් ක්‍රියාත්මක කිරීමට සුදුසුම ක්‍රමය findකුමක්ද?


13
මම හිතන්නේ මෙය "කිසි විටෙකත් ප්‍රතිදානය විග්‍රහ නොකරන්න!" - ඔබට නිසැකවම එක් අතකින් එකක් කළ හැකිය, නමුත් ඒවා නිෂ්පාදන ගුණාත්මක භාවයට වඩා ඉක්මන් කඩාවැටීමකි. නැතහොත්, වඩාත් සාමාන්‍යයෙන්, කිසි විටෙකත් ප්‍රබන්ධ නොවන්න.
ru ස් එඩිගර්


මෙය කැනොනිකල් පිළිතුරක් බවට පත් කළ යුතුය
සයිඩ්

6
සොයාගැනීමේ ලක්ෂ්‍යය වන්නේ එය සොයා ගන්නා දෙය ඉක්මවා යාමයි.
OrangeDog

2
එක් සහායක ලක්ෂ්‍යයක් - ඔබට ප්‍රතිදානය ගොනුවකට යැවීමට අවශ්‍ය විය හැකිය, පසුව එය ස්ක්‍රිප්ටයේ පසුව සකසන්න. ඔබට ස්ක්‍රිප්ට් නිදොස් කිරීමට අවශ්‍ය නම් ගොනු ලැයිස්තුව සමාලෝචනය සඳහා ලබා ගත හැකිය.
user117529

Answers:


97

ගැටලුව වන්නේ

for f in $(find .)

නොගැලපෙන කරුණු දෙකක් ඒකාබද්ධ කරයි.

findනව රේඛා අක්ෂර මගින් වෙන් කරන ලද ගොනු මාර්ග ලැයිස්තුවක් මුද්‍රණය කරයි. $(find .)එම ලැයිස්තු සන්දර්භය තුළ ඔබ සඳහන් නොකළ විට එය කැඳවනු ලබන භේදය + ග්ලෝබ් ක්‍රියාකරු $IFS(පෙරනිමියෙන් නව රේඛාව පමණක් නොව අවකාශය සහ ටැබ් (සහ එන්.යූ.එල් zsh) ද ඇතුළත් වේ. in zsh) (සහ ksh93 හෝ pdksh ව්‍යුත්පන්නයන්හි වරහන් ප්‍රසාරණය පවා!).

ඔබ එය සෑදුවත්:

IFS='
' # split on newline only
set -o noglob # disable glob (also disables brace expansion in pdksh
              # but not ksh93)
for f in $(find .) # invoke split+glob

නව රේඛා අක්‍ෂරය ගොනු මාර්ගයක ඇති තරම් වලංගු බැවින් එය තවමත් වැරදිය. ප්‍රතිදානය find -printහුදෙක් විශ්වාසදායක ලෙස පශ්චාත් සැකසුම් කළ නොහැකි ය ( මෙහි පෙන්වා ඇති පරිදි සමහර කැටි ගැසුණු උපක්‍රම භාවිතා කිරීමෙන් හැර ).

එහි අර්ථය වන්නේ කවචයට ප්‍රතිදානය findසම්පුර්ණයෙන්ම ගබඩා කළ යුතු අතර , පසුව ලිපිගොනු විවර කිරීමට පෙර එය බෙදන්න + ග්ලෝබ් කරන්න (එයින් අදහස් කරන්නේ එම ප්‍රතිදානය දෙවන වරටත් මතකයේ ගබඩා කිරීමයි).

find . | xargs cmdසමාන ගැටළු ඇති බව සලකන්න (එහි, හිස්, නව රේඛාව, තනි උපුටා දැක්වීම, ද්විත්ව උපුටා දැක්වීම සහ බැක්ස්ලෑෂ් (සහ සමහර xargක්‍රියාත්මක කිරීම් සමඟ බයිට් වලංගු අක්ෂරවල කොටසක් නොවීම) ගැටළුවක් වේ)

වඩාත් නිවැරදි විකල්ප

එකක් භාවිතා කිරීමට ඇති එකම මාර්ගය වන forප්රතිදානය මත ලූප findභාවිතා කිරීමට වනු ඇත zshසහය දැක්වීම IFS=$'\0'සහ:

IFS=$'\0'
for f in $(find . -print0)

(ආදේශ -print0සමග -exec printf '%s\0' {} +සඳහා findඅද කාලයේ නොවන සම්මත (නමුත් ඉතා පොදු සහාය දෙන බව) නැහැ නිර්මාණයන් -print0).

මෙන්න, නිවැරදි හා අතේ ගෙන යා හැකි ක්‍රමය භාවිතා කිරීම -exec:

find . -exec something with {} \;

නැතහොත් somethingතර්ක එකකට වඩා ගත හැකි නම් :

find . -exec something with {} +

ඔබට එම ලිපිගොනු ලැයිස්තුව ෂෙල් එකකින් හැසිරවීමට අවශ්‍ය නම්:

find . -exec sh -c '
  for file do
    something < "$file"
  done' find-sh {} +

(පරෙස්සම් වන්න එය එකකට වඩා ආරම්භ විය හැක sh).

සමහර පද්ධති වල, ඔබට මෙය භාවිතා කළ හැකිය:

find . -print0 | xargs -r0 something with

ඇති සාමාන්ය වාක්ය රීති හා මාධ්යයන් මත කුඩා වාසිය නමුත් somethingගේ stdinඑක්කෝ නල හෝ /dev/null.

ඔබට එය භාවිතා කිරීමට අවශ්‍ය විය හැකි එක් හේතුවක් වන්නේ සමාන්තර සැකසුම් සඳහා -PGNU විකල්පය භාවිතා කිරීමයි xargs. මෙම stdinප්රශ්නය ද GNU සමග පමණ වැඩ කළ හැකි xargsසමග -aෂෙල් වෙඩි ක්රියාවලිය ආදේශන සහාය සමඟ විකල්පය:

xargs -r0n 20 -P 4 -a <(find . -print0) something

නිදසුනක් ලෙස, somethingගොනු තර්ක 20 ක් ගන්නා එක් එක් සමගාමී ආයාචනා 4 ක් දක්වා ධාවනය කිරීම .

සමඟ zshහෝ bash, ප්‍රතිදානයට වඩා ලූපයක් ලබා ගත හැකි තවත් ක්‍රමයක් find -print0වන්නේ:

while IFS= read -rd '' file <&3; do
  something "$file" 3<&-
done 3< <(find . -print0)

read -d '' නව රේඛා වෙන්කර ඇති ඒවා වෙනුවට NUL වෙන් කළ වාර්තා කියවයි.

bash-4.4සහ ඊට ඉහළින් ඇති ලිපිගොනු find -print0අරාවකින් ගබඩා කළ හැකිය :

readarray -td '' files < <(find . -print0)

මෙම zshසමාන (ආරක්ෂා කර ගැනීමේ වාසිය ඇති findපිටවීමේ තත්ත්වය 's):

files=(${(0)"$(find . -print0)"})

සමඟ zsh, ඔබට බොහෝ findප්‍රකාශන ග්ලෝබ් සුදුසුකම් සහිත පුනරාවර්තන ග්ලෝබිං සංයෝජනයකට පරිවර්තනය කළ හැකිය . නිදසුනක් ලෙස, ලිහිල් කිරීම find . -name '*.txt' -type f -mtime -1වනුයේ:

for file (./**/*.txt(ND.m-1)) cmd $file

හෝ

for file (**/*.txt(ND.m-1)) cmd -- $file

(අවශ්යතාවය පරෙස්සම් --සමග මෙන් **/*, ගොනු මාර්ග සමඟ ආරම්භ නොමැත ./, ඒ සමඟ ආරම්භ කළ හැක -උදාහරණයක්).

ksh93හා bashඅවසානයේ සඳහා සහය එක් **/(වැඩි ආවර්තනික globbing ආකාර අත්තිකාරම් ඇතත්), නමුත් භාවිතය වන පරිදි තවමත් glob සුදුසුකම් නොමැති **ඉතා එහි සීමා විය. bash4.3 ට පෙර ඩිරෙක්ටරි ගසෙන් බැසීමේදී සිම්ලින්ක් අනුගමනය කරන බවට පරිස්සම් වන්න .

පෙරළීම සඳහා මෙන් $(find .), එයින් අදහස් වන්නේ මතක ගොනු 1 හි ඇති මුළු ගොනු ලැයිස්තුවම ගබඩා කිරීමයි . සමහර අවස්ථාවලදී ලිපිගොනු පිළිබඳ ඔබේ ක්‍රියාවන් ලිපිගොනු සොයා ගැනීම කෙරෙහි බලපෑමක් ඇති කිරීමට ඔබ අකමැති වුවද එය යෝග්‍ය වේ (ඔබ සොයාගත හැකි තවත් ලිපිගොනු එකතු කරන විට වැනි).

වෙනත් විශ්වසනීයත්වය / ආරක්ෂක කරුණු

තරඟ කොන්දේසි

දැන්, අපි විශ්වසනීයත්වය ගැන කතා කරන්නේ නම්, කාලය find/ ධාවන zshගොනුව සොයා ගැනීම සහ එය නිර්ණායක හා එය භාවිතා කරන වේලාව ( TOCTOU race ) අතර ඇති ධාවන කොන්දේසි සඳහන් කළ යුතුය.

ඩිරෙක්ටරි ගසකින් බැසීමේදී පවා, සිම්ලින්ක් අනුගමනය නොකිරීමට වග බලා ගත යුතු අතර TOCTOU තරඟයකින් තොරව එය කළ යුතුය. find( findඅවම වශයෙන් GNU ) එය කරන්නේ openat()නිවැරදි O_NOFOLLOWධජ භාවිතා කරමින් නාමාවලි විවෘත කිරීමෙන් (සහය දක්වන තැන) සහ එක් එක් නාමාවලිය සඳහා ගොනු විස්තරයක් විවෘතව තබා ගැනීමෙන් zsh/ bash/ kshඑසේ නොකරන්න. එබැවින් ප්‍රහාරකයෙකුට නියම වේලාවට නාමාවලියක් සිම්ලින්ක් සමඟ ප්‍රතිස්ථාපනය කිරීමට හැකි වූ විට, ඔබට වැරදි නාමාවලියෙන් බැස යා හැකිය.

findනාමාවලිය නිසියාකාරව බැස ගියත් , -exec cmd {} \;ඊටත් වඩා වැඩි ගණනක් -exec cmd {} +එක් වරක් cmdක්‍රියාත්මක කළත් , නිදසුනක් ලෙස cmd ./foo/barහෝ cmd ./foo/bar ./foo/bar/bazකාලය cmdභාවිතා කරන විට ./foo/bar, ගුණාංග barතවදුරටත් ගැලපෙන නිර්ණායක සපුරාලන්නේ නැත find, නමුත් ඊටත් වඩා නරක ./fooවිය හැකිය. වෙනත් යම් ස්ථානයක් වෙත symlink වෙනුවට (සහ ජාතිය කවුළුව සමග ගොඩක් විශාල කර ඇත -exec {} +එහිදී findබොත්තමක් ඔබා එය කතා කිරීමට තරම් ගොනු කිරීමට cmd).

සමහර findක්‍රියාවට -execdirනැංවීමේදී (සම්මත නොවන) දෙවන ගැටළුව සමනය කිරීම සඳහා පුරෝකථනයක් ඇත.

සමඟ:

find . -execdir cmd -- {} \;

find chdir()ක්‍රියාත්මක වීමට පෙර ගොනුවේ මව් නාමාවලියට cmd. ඇමතීම වෙනුවට cmd -- ./foo/bar, එය අමතයි cmd -- ./bar( cmd -- barසමහර ක්‍රියාත්මක කිරීම් සමඟ, එබැවින් --), එබැවින් ./fooසිම්ලින්ක් වෙත වෙනස් කිරීමේ ගැටළුව මඟහරවා ගත හැකිය. එමඟින් rmආරක්ෂිත වැනි විධානයන් භාවිතා කරයි (එයට තවමත් වෙනත් ගොනුවක් ඉවත් කළ හැකිය, නමුත් වෙනත් නාමාවලියක ඇති ගොනුවක් නොවේ), නමුත් සමමුහුර්ත අනුගමනය නොකිරීමට සැලසුම් කර ඇත්නම් මිස ගොනු වෙනස් කළ හැකි විධාන නොවේ.

-execdir cmd -- {} +සමහර විට ද ක්‍රියා කරන නමුත් GNU findහි සමහර අනුවාදයන් ඇතුළු ක්‍රියාත්මක කිරීම් කිහිපයක් සමඟ එය සමාන වේ -execdir cmd -- {} \;.

-execdir ඉතා ගැඹුරු නාමාවලි ගස් හා සම්බන්ධ සමහර ගැටලු සමඟ කටයුතු කිරීමේ වාසිය ද ඇත.

තුළ:

find . -exec cmd {} \;

ලබා දී ඇති මාවතේ ප්‍රමාණය cmdගොනුව ඇති ඩිරෙක්ටරියේ ගැඹුර සමඟ වර්ධනය වේ. එම ප්‍රමාණය PATH_MAX(ලිනක්ස් හි 4k වැනි) වඩා විශාල cmdවුවහොත්, එම මාර්ගයේ සිදුවන ඕනෑම පද්ධති ඇමතුමක් ENAMETOOLONGදෝෂයකින් අසමත් වේ .

සමඟ -execdir, ගොනුවේ නම පමණක් (සමහර විට උපසර්ගය සහිතව ./) ලබා දෙනු cmdලැබේ. බොහෝ ගොනු පද්ධතිවල ඇති ගොනු නම් වලට වඩා අඩු සීමාවක් ( NAME_MAX) ඇත PATH_MAX, එබැවින් ENAMETOOLONGදෝෂය ඇතිවීමට ඇති ඉඩකඩ අඩුය.

බයිට්ස් එදිරිව අක්ෂර

බොහෝ විට findයුනික්ස් වැනි පද්ධති වල ගොනු නාමයන් බයිට් අනුක්‍රමයකි (ඕනෑම බයිට් අගයක් නමුත් ගොනු මාර්ගයක 0, සහ බොහෝ පද්ධතිවල) (සාමාන්‍යයෙන් ගොනු නාම හැසිරවීමේදී) ආරක්ෂාව ගැන සැලකිලිමත් වන විට බොහෝ විට නොසලකා හරිනු ලැබේ. ASCII මත පදනම් වූ ඒවා, අපි දැනට දුර්ලභ EBCDIC පදනම් කරගත් ඒවා නොසලකා හරිනු ඇත) 0x2f යනු මාර්ගය පරිසීමකය).

එම බයිට් පෙළ ලෙස සලකා බැලීමට අවශ්‍ය දැයි තීරණය කිරීම යෙදුම් සතු ය. ඔවුන් සාමාන්‍යයෙන් එසේ කරයි, නමුත් සාමාන්‍යයෙන් බයිට් වලින් අක්ෂර වලට පරිවර්තනය කිරීම පරිශීලකයාගේ ස්ථානය මත පදනම්ව පරිසරය මත පදනම් වේ.

එහි තේරුම නම්, ලබා දී ඇති ගොනු නාමයකට පෙදෙසි අනුව වෙනස් පෙළ නිරූපණයක් තිබිය හැකිය. නිදසුනක් ලෙස, බයිට් අනුක්‍රමය 63 f4 74 e9 2e 74 78 74වනුයේ côté.txtඅක්ෂර කට්ටලය ISO-8859-1 cєtщ.txtවන පෙදෙසක එම ලිපිගොනු නාමය අර්ථ නිරූපණය කරන යෙදුමක් සඳහා වන අතර ඒ වෙනුවට අක්ෂර කට්ටලය IS0-8859-5 වේ.

වඩාත් නරක ය. අක්ෂර කට්ටලය යූටීඑෆ් -8 (වර්තමානයේ සාමාන්‍යය) ඇති ප්‍රදේශයක, 63 f4 74 e9 2e 74 78 74 අක්ෂරවලට අනුරූපණය කළ නොහැක!

findගොනු නාම එහි -name/ -pathඅනාවැකි සඳහා පෙළක් ලෙස සලකන එවැනි යෙදුමකි (සහ තවත්, සමහර ක්‍රියාත්මක කිරීම් වැනි -inameහෝ වැඩි ගණනක් -regex).

එහි තේරුම නම්, උදාහරණයක් ලෙස, findක්‍රියාත්මක කිරීම් කිහිපයක් සමඟ (GNU ද ඇතුළුව find).

find . -name '*.txt'

63 f4 74 e9 2e 74 78 74යූටීඑෆ් -8 පෙදෙසක *( අක්ෂර 0 හෝ ඊට වැඩි ගණනක් ගැලපෙන , බයිට් නොව) එම අක්ෂර නොවන අක්ෂර සමඟ නොගැලපෙන බැවින් ඉහත අපගේ ගොනුව සොයාගත නොහැකි වනු ඇත .

LC_ALL=C find... සී පෙදෙසි අක්ෂරයකට එක් බයිට් එකක් අදහස් කරන අතර (සාමාන්‍යයෙන්) සියලු බයිට් අගයන් අක්ෂරයකට සිතියම් ගත කරන බවට සහතික වන බැවින් (සමහර බයිට් අගයන් සඳහා නිර්වචනය නොකළ ඒවා විය හැක).

දැන් එම ලිපිගොනු ෂෙල් එකකින් ලූප කිරීම ගැන කතා කරන විට, එම බයිට් එදිරිව අක්‍ෂරය ද ගැටළුවක් විය හැකිය. අපි සාමාන්‍යයෙන් ප්‍රධාන ෂෙල් වෙඩි 4 ක් දකිමු:

  1. තවමත් බහු-බයිට් නොදන්නා අය වැනි dash. ඔවුන් සඳහා, බයිට් අක්ෂරයකට සිතියම් ගත කරයි. උදාහරණයක් ලෙස, UTF-8 හි côtéඅක්ෂර 4 ක් ඇත, නමුත් බයිට් 6 කි. යූටීඑෆ් -8 අක්ෂර වින්‍යාසය ඇති පෙදෙසක, දී

    find . -name '????' -exec dash -c '
      name=${1##*/}; echo "${#name}"' sh {} \;
    

    findයූටීඑෆ් -8 හි කේතනය කර ඇති අක්ෂර 4 කින් සමන්විත ලිපිගොනු සාර්ථකව සොයාගනු ඇත, නමුත් dashදිග 4 ත් 24 ත් අතර දිග වාර්තා කරයි.

  2. yash: ප්‍රතිවිරුද්ධ. එය ගනුදෙනු කරන්නේ චරිත සමඟ පමණි . එය ගන්නා සියලුම ආදාන අභ්‍යන්තරව අක්ෂර වලට පරිවර්තනය වේ. එය වඩාත් ස්ථාවර කවචයක් සාදයි, නමුත් එයින් අදහස් කරන්නේ එයට අත්තනෝමතික බයිට් අනුක්‍රමයන් (වලංගු අක්ෂර වලට පරිවර්තනය නොකරන) සමඟ කටයුතු කළ නොහැකි බවයි. සී පෙදෙසෙහි වුවද, 0x7f ට වඩා වැඩි බයිට් අගයන් සමඟ කටයුතු කළ නොහැක.

    find . -exec yash -c 'echo "$1"' sh {} \;
    

    côté.txtඋදාහරණයක් ලෙස UTF-8 පෙදෙසක අපගේ ISO-8859-1 මත අසමත් වනු ඇත .

  3. බහු-බයිට් සහාය ක්‍රමයෙන් එකතු කර ඇති bashහෝ කැමති අය zsh. ඒවා අක්ෂර ලෙස සිතියම් ගත කළ නොහැකි බයිට් සලකා බැලීමට නැවත වැටෙනු ඇත. GBK හෝ BIG5-HKSCS වැනි අඩු බහු-බයිට් අක්ෂර කට්ටල සමඟ ඔවුන් සතුව තවමත් දෝෂ කිහිපයක් තිබේ (ඒවායේ බහු-බයිට් අක්ෂර 0-127 පරාසය තුළ (ASCII අක්ෂර වැනි) බයිට් අඩංගු බැවින් ඒවා ඉතා අශෝභන වේ. ).

  4. වගේ අය sh(අවම වශයෙන් 11) ඒ අතරින් කිහිපයකි හෝ mksh -o utf8-modeසහාය ලබා දෙන නමුත්, UTF-8 සඳහා පමණක් බහු-බයිට්.

සටහන්

1 සම්පූර්ණත්වය සඳහා, zshසම්පූර්ණ ලැයිස්තුවම මතකයේ ගබඩා නොකර පුනරාවර්තන ග්ලෝබින් භාවිතයෙන් ලිපිගොනු ලූපයක් බවට පත්කිරීමේ ක්‍රමයක් අපට සඳහන් කළ හැකිය :

process() {
  something with $REPLY
  false
}
: **/*(ND.m-1+process)

+cmdයනු cmdවර්තමාන ගොනු මාර්ගය සමඟ (සාමාන්‍යයෙන් ශ්‍රිතයක්) කැඳවන ග්ලෝබ් සුදුසුකම්යකි $REPLY. ගොනුව තෝරා ගත යුතුද යන්න තීරණය කිරීම සඳහා ශ්‍රිතය සත්‍ය හෝ අසත්‍යය ලබා දෙයි (තවද අරාවෙහි ඇති $REPLYගොනු කිහිපයක් වෙනස් කිරීමට හෝ ආපසු ලබා දීමටද පුළුවන $reply). මෙන්න අපි එම ශ්‍රිතයේ සැකසුම් සිදු කර අසත්‍යය නැවත ලබා දෙන්නෙමු එවිට ගොනුව තෝරා නොගනී.


නිවැරදි මාර්ගය භාවිතා කිරීමට බව සාධකයක් වන්නේ එයයි find . -exec something with {} \;හෝ find . -print0 | xargs -r0 something with? කෙසේ වෙතත්, මට ලූපයට something withඇතුළත් කළ හැකි කේත රේඛා අඩංගු වන ශ්‍රිතයක් / පිටපතක් ලිවීමට forඅවශ්‍යද? ස්තූතියි.
ජොෂ්

188

findනිමැවුමට වඩා ලූප වීම නරක පුරුද්දක් වන්නේ ඇයි?

සරල පිළිතුර නම්:

ගොනු නාමවල ඕනෑම අක්ෂරයක් අඩංගු විය හැකි බැවිනි.

එබැවින්, ගොනු නාම සීමා කිරීම සඳහා ඔබට විශ්වාසදායක ලෙස භාවිතා කළ හැකි මුද්‍රිත අක්‍ෂරයක් නොමැත.


ලිපිගොනු නාම සීමා කිරීම සඳහා නව රේඛා බොහෝ විට (වැරදි ලෙස) භාවිතා කරයි, මන්ද ගොනු නාමවල නව රේඛා අක්ෂර ඇතුළත් කිරීම අසාමාන්‍යය .

කෙසේ වෙතත්, ඔබ ඔබේ මෘදුකාංගය අත්තනෝමතික උපකල්පන වටා ගොඩනගන්නේ නම්, ඔබ අසාමාන්‍ය අවස්ථාවන් හසුරුවා ගැනීමට අසමත් වන අතර නරකම ලෙස ඔබේ පද්ධතියේ පාලනය ලබා දෙන ද්වේෂ සහගත සූරාකෑමට විවෘත වේ. එබැවින් එය ශක්තිමත් බව සහ ආරක්ෂාව පිළිබඳ ප්‍රශ්නයකි.

ඔබට විවිධ ආකාර දෙකකින් මෘදුකාංග ලිවිය හැකි අතර, ඉන් එකක් එජ් කේස් (අසාමාන්‍ය යෙදවුම්) නිවැරදිව හසුරුවයි, නමුත් අනෙක කියවීමට පහසු නම්, වෙළඳාමක් ඇති බවට ඔබට තර්ක කළ හැකිය. (මම කැමති නැහැ. මම නිවැරදි කේතයට කැමතියි.)

කෙසේ වෙතත්, කේතයේ නිවැරදි, ශක්තිමත් අනුවාදය කියවීමට පහසු නම්, එජ් අවස්ථා වලදී අසමත් වන කේත ලිවීමට නිදහසට කරුණක් නැත. මෙම ප්රශ්නය වන්නේ findඑක් එක් ගොනුව හමු මත විධානය ක්රියාත්මක කිරීමේ අවශ්යතාව.


අපි වඩාත් නිශ්චිතව කියමු: යුනික්ස් හෝ ලිනක්ස් පද්ධතියක, ගොනු නාමයන් හැර වෙනත් අක්ෂරයක් අඩංගු විය හැකිය /(එය මාර්ග සංරචක බෙදුම්කරුවෙකු ලෙස භාවිතා කරයි), සහ ඒවා ශුන්‍ය බයිට් අඩංගු නොවිය හැකිය.

එබැවින් ගොනු නාම සීමා කිරීමට ඇති එකම නිවැරදි ක්‍රමය ශුන්‍ය බයිට් ය .


GNU findහි -print0ප්‍රාථමිකයක් ඇතුළත් වන අතර එය මුද්‍රණය කරන ගොනු නාමයන් සීමා කිරීම සඳහා ශුන්‍ය බයිට් එකක් භාවිතා කරන බැවින්, GNU සහ එහි ධජය (සහ ධජය) සමඟ ආරක්ෂිතව භාවිතා find කළ හැකිය :xargs-0-rfind

find ... -print0 | xargs -r0 ...

කෙසේ වෙතත්, මෙම පෝරමය භාවිතා කිරීමට හොඳ හේතුවක් නැත , මන්ද:

  1. එය එහි තිබිය යුතු නොවන GNU සොයාගැනීම් මත යැපීමක් එක් කරයි, සහ
  2. findඇත නිර්මාණය , එය සම්බ ගොනු මත විධානයන් ක්රියාත්මක වීමට හැකි විය.

එසේම, GNU xargsසඳහා අවශ්‍ය වන -0අතර -r, FreeBSD සඳහා xargsපමණක් අවශ්‍ය වන අතර -0( -rවිකල්පයක් නොමැත ), සමහරු xargsකිසිසේත් සහාය නොදක්වයි -0. එබැවින් POSIX විශේෂාංග වලට ඇලී සිටීම වඩාත් සුදුසුය find(ඊළඟ කොටස බලන්න) සහ මඟ හරින්න xargs.

ලක්ෂ්‍ය 2— findහි සොයාගත් ලිපිගොනු වල විධාන ක්‍රියාත්මක කිරීමේ හැකියාව සම්බන්ධයෙන් - මයික් ලූකයිඩ්ස් එය වඩාත් සුදුසු යැයි කීවේය:

findගේ ව්‍යාපාරය ප්‍රකාශන ඇගයීමකි - ලිපිගොනු සොයා ගැනීම නොවේ. ඔව්, findනිසැකවම ලිපිගොනු සොයා ගනී; නමුත් එය ඇත්තෙන්ම අතුරු ආබාධයකි.

- යුනික්ස් බල මෙවලම්


POSIX හි නිශ්චිත භාවිතයන් find

එක් එක් findප්‍රති results ල සඳහා විධාන එකක් හෝ කිහිපයක් ක්‍රියාත්මක කිරීමට සුදුසුම ක්‍රමය කුමක්ද?

සොයාගත් සෑම ගොනුවක් සඳහාම එක් විධානයක් ක්‍රියාත්මක කිරීමට, භාවිතා කරන්න:

find dirname ... -exec somecommand {} \;

සොයාගත් සෑම ගොනුවක් සඳහාම අනුපිළිවෙලින් බහුවිධ විධානයන් ක්‍රියාත්මක කිරීම සඳහා, දෙවන විධානය ක්‍රියාත්මක කළ යුත්තේ පළමු විධානය සාර්ථක වුවහොත් පමණි:

find dirname ... -exec somecommand {} \; -exec someothercommand {} \;

එකවර බහු ගොනු වල තනි විධානයක් ක්‍රියාත්මක කිරීමට:

find dirname ... -exec somecommand {} +

find සමඟ sh

ප්‍රතිදානය යළි හරවා යැවීම හෝ ගොනු නාමයෙන් දිගුවක් ඉවත් කිරීම හෝ ඒ හා සමාන දෙයක් වැනි විධානයන්හි ෂෙල් අංග භාවිතා කිරීමට ඔබට අවශ්‍ය නම් , ඔබට sh -cඉදිකිරීම් භාවිතා කළ හැකිය . ඔබ මේ ගැන කරුණු කිහිපයක් දැන සිටිය යුතුය:

  • කිසි විටෙකත් කේතයට {}කෙලින්ම ඇතුළත් නොකරන්නsh . අනිෂ්ට ලෙස සැකසූ ගොනු නාම වලින් අත්තනෝමතික කේත ක්‍රියාත්මක කිරීමට මෙය ඉඩ දෙයි. එසේම, එය ඇත්ත වශයෙන්ම POSIX විසින් නිශ්චිතව දක්වා නොමැති අතර එය කිසිසේත් ක්‍රියාත්මක වනු ඇත. (ඊළඟ කරුණ බලන්න.)

  • {}කිහිප වතාවක් භාවිතා නොකරන්න , නැතහොත් දිගු තර්කයක කොටසක් ලෙස එය භාවිතා නොකරන්න. මෙය අතේ ගෙන යා නොහැක. උදාහරණයක් ලෙස, මෙය නොකරන්න:

    find ... -exec cp {} somedir/{}.bak \;

    POSIX පිරිවිතරයන්find උපුටා දැක්වීමට :

    නම්, එවැනි utility_name හෝ තර්කය string චරිත දෙකක් අඩංගු වේ "{}", නමුත් චරිත දෙකක් පමණක් නොව "{}", එය ක්රියාත්මක කිරීම අර්ථ යන්නයි සොයා එම චරිත දෙකක් විස්ථාපනය හෝ වෙනසක් නොමැතිව වැල භාවිතා කරයි.

    ... "{}" අක්ෂර දෙක අඩංගු තර්ක එකකට වඩා තිබේ නම්, හැසිරීම නිශ්චිතව දක්වා නැත.

  • -cවිකල්පය වෙත සම්මත කරන ලද ෂෙල් විධාන නූලට පසුව ඇති තර්ක , ආරම්භයෙන් ෂෙල්හි$0 ස්ථානීය පරාමිතීන් වෙත සකසා ඇත . ආරම්භ නොවේ $1.

    මේ හේතුව නිසා, "ව්‍යාජ" $0අගයක් ඇතුළත් කිරීම හොඳය , එනම් find-sh, බිහි වූ කවචය තුළ සිට දෝෂ වාර්තා කිරීම සඳහා භාවිතා කරනු ඇත. එසේම, මෙය "$@"බොහෝ ලිපිගොනු කවචයට යවන විට වැනි ඉදිකිරීම් භාවිතා කිරීමට ඉඩ ලබා දෙන අතර, අගයක් මඟ හැරීම යනු $0සම්මත කළ පළමු ගොනුව සකසා ඇති $0අතර එමඟින් ඇතුළත් නොවේ "$@".


එක් ගොනුවකට තනි කවච විධානයක් ක්‍රියාත්මක කිරීමට, භාවිතා කරන්න:

find dirname ... -exec sh -c 'somecommandwith "$1"' find-sh {} \;

කෙසේ වෙතත් එය සාමාන්‍යයෙන් ෂෙල් ලූපයක ගොනු හැසිරවීමට වඩා හොඳ කාර්ය සාධනයක් ලබා දෙනු ඇත, එවිට ඔබ සොයාගත් සෑම ගොනුවක් සඳහාම කවචයක් බිහි නොකරනු ඇත:

find dirname ... -exec sh -c 'for f do somecommandwith "$f"; done' find-sh {} +

( එක් එක් ස්ථානීය පරාමිතීන්ට for f doසමාන වන අතර for f in "$@"; doඒවා හසුරුවන බව සලකන්න other වෙනත් වචන වලින් කිවහොත්, සොයාගත් එක් එක් ලිපිගොනු findඒවායේ නම්වල ඇති විශේෂ අක්ෂර නොසලකා එය භාවිතා කරයි .)


නිවැරදි findභාවිතය පිළිබඳ තවත් උදාහරණ :

(සටහන: මෙම ලැයිස්තුව දීර් extend කිරීමට නිදහස් වන්න.)


5
findප්‍රතිදානය විග්‍රහ කිරීමට විකල්පයක් ගැන මා නොදන්නා එක් අවස්ථාවක් තිබේ - එහිදී ඔබට එක් එක් ගොනුව සඳහා වත්මන් කවචයේ විධාන ක්‍රියාත්මක කළ යුතුය (උදා: ඔබට විචල්‍යයන් සැකසීමට අවශ්‍ය නිසා). මේ අවස්ථාවේ දී, while IFS= read -r -u3 -d '' file; do ... done 3< <(find ... -print0)මම දන්නා හොඳම මෝඩය. සටහන්: <( )අතේ ගෙන යා නොහැක - bash හෝ zsh භාවිතා කරන්න. එසේම, -u3සහ 3<stdin කියවීමට පුඩුවක් උත්සාහක දිනුම් තුල නඩුව කිසිම දෙයක් ඇත.
ගෝර්ඩන් ඩේවිසන්

1
Ord ගෝර්ඩන් ඩේවිසන්, සමහර විට - නමුත් ඔබට එම විචල්‍යයන් සැකසීමට අවශ්‍ය වන්නේ කුමක්ද? මම ඕනෑම දෙයක් එය කටයුතු කළ යුතු බව තර්ක කරන තුල ඇති find ... -execඇමතුම. නැතහොත් එය ඔබේ භාවිත නඩුව හසුරුවන්නේ නම් ෂෙල් ග්ලෝබ් භාවිතා කරන්න.
වයිල්ඩ්කාඩ්

1
ලිපිගොනු සැකසීමෙන් පසු සාරාංශයක් මුද්‍රණය කිරීමට මට බොහෝ විට අවශ්‍ය වේ ("2 පරිවර්තනය, 3 මඟ හැරුණි, පහත ලිපිගොනු වල දෝෂ තිබේ: ..."), සහ එම ගණන් / ලැයිස්තු ෂෙල් විචල්‍යයන්ගෙන් එකතු කර ගත යුතුය. එසේම, ලිපිගොනු පෙළක් සෑදීමට අවශ්‍ය අවස්ථා තිබේ, එවිට මට අනුපිළිවෙලට වඩා සංකීර්ණ දේවල් කළ හැකිය (එවැනි අවස්ථාවකදී filelist=(); while ... do filelist+=("$file"); done ...).
ගෝර්ඩන් ඩේවිසන්

3
ඔබේ පිළිතුර නිවැරදි ය. කෙසේ වෙතත් මම ප්‍රවාදයට කැමති නැත. මම වඩා හොඳින් දැන සිටියද, බොහෝ (විශේෂයෙන් අන්තර්ක්‍රියාකාරී) භාවිත අවස්ථා තිබේ, එය ආරක්ෂිත සහ findප්‍රතිදානය මත ලූප ටයිප් කිරීම පහසු හෝ ඊටත් වඩා නරක ලෙස භාවිතා lsකරයි. මම දිනපතා මෙය කරන්නේ ගැටළු නොමැතිව ය. සියලු වර්ගවල මෙවලම්වල -print0, --null, -z හෝ -0 විකල්ප ගැන මම දනිමි. නමුත් ඇත්ත වශයෙන්ම අවශ්‍ය නම් මිස ඒවා මගේ අන්තර්ක්‍රියාකාරී ෂෙල් විමසුමේ භාවිතා කිරීමට කාලය නාස්ති නොකරමි. මෙය ඔබගේ පිළිතුරෙහි ද සටහන් කළ හැකිය.
රුඩිමියර්

17
ud රුඩිමියර්, ඩොග්මා එදිරිව හොඳම පුරුද්ද පිළිබඳ තර්කය දැනටමත් මරණය දක්වා සිදු කර ඇත. උනන්දුවක් නැත. ඔබ එය අන්තර්ක්‍රියාකාරී ලෙස භාවිතා කරන්නේ නම් සහ එය ක්‍රියාත්මක වන්නේ නම් හොඳයි, හොඳයි, නමුත් මම එය ප්‍රවර්ධනය කිරීමට යන්නේ නැහැ. ශක්තිමත් කේතය ගැන ඉගෙනගෙන ඒ කරන්න කරදර කරන තිර රචනය කතුවරුන් ප්රතිශතය බව පමණක් පමණක් ඔවුන් කරන්නේ කුමක් කරන්නේ වෙනුවට, නිෂ්පාදනය පිටපත් රචනය විට කරන්නේ කිරීම සඳහා භාවිතා අනොන්ය ඉතා අවම වේ. හැසිරවීම යනු සෑම විටම හොඳම භාවිතයන් ප්‍රවර්ධනය කිරීමයි. දේවල් කිරීමට නිවැරදි ක්‍රමයක් ඇති
වයිල්ඩ්කාඩ්

11

මෙම පිළිතුර ඉතා විශාල ප්‍රති result ල කට්ටල සඳහා වන අතර ප්‍රධාන වශයෙන් කාර්ය සාධනය ගැන සැලකිලිමත් වේ, උදාහරණයක් ලෙස මන්දගාමී ජාලයක් හරහා ලිපිගොනු ලැයිස්තුවක් ලබා ගැනීමේදී. කුඩා ගොනු ප්‍රමාණයක් සඳහා (දේශීය තැටියක 100 ක් හෝ 1000 ක් පවා කියන්න) මෙයින් බොහොමයක් වැදගත් වේ.

සමාන්තරකරණය සහ මතක භාවිතය

ලබා දී ඇති අනෙක් පිළිතුරු හැරුණු විට, වෙන්වීමේ ගැටළු හා සම්බන්ධ තවත් කරුණු තිබේ

for file in `find . -type f -name ...`; do smth with ${file}; done

රේඛීය කඩනයන් මත බෙදීමට පෙර, පිටුපස ඇති කොටස මුලින්ම ඇගයීමට ලක් කළ යුතුය. මෙයින් අදහස් කරන්නේ, ඔබට විශාල ලිපිගොනු ප්‍රමාණයක් ලැබෙන්නේ නම්, එය විවිධ සංරචකවල ඇති ඕනෑම ප්‍රමාණයේ සීමාවන් යටපත් කළ හැකිය; සීමාවන් නොමැති නම් ඔබට මතක ශක්තිය නැති වී යා හැකිය; ඕනෑම අවස්ථාවක, ඔබේ පළමු ලැයිස්තුව ක්‍රියාත්මක කිරීමට පෙර මුළු ලැයිස්තුවම ප්‍රතිදානය කර findවිග්‍රහ කරන තෙක් ඔබ බලා සිටිය යුතුය .forsmth

වඩාත් කැමති යුනික්ස් ක්‍රමය වන්නේ සහජයෙන්ම සමාන්තරව ක්‍රියාත්මක වන පයිප්ප සමඟ වැඩ කිරීම සහ පොදුවේ අත්තනෝමතික ලෙස විශාල බෆර අවශ්‍ය නොවේ. එයින් අදහස් වන්නේ: ඔබට වඩා findසමාන්තරව ධාවනය වීමට ඔබ වැඩි කැමැත්තක් දක්වන smthඅතර වත්මන් ගොනු නාමය RAM හි තබා ගන්න smth.

ඒ සඳහා අවම වශයෙන් අර්ධ වශයෙන් හරි විසඳුමක් වනුයේ ඉහත සඳහන් කළ දෙයයි find -exec smth. එමඟින් සියලුම ගොනු නාමයන් මතකයේ තබා ගැනීමේ අවශ්‍යතාවය ඉවත් කරන අතර සමාන්තරව හොඳින් ක්‍රියාත්මක වේ. අවාසනාවට, එය smthඑක් ගොනුවකට එක් ක්‍රියාවලියක් ආරම්භ කරයි. smthඑක් ගොනුවක පමණක් වැඩ කළ හැකි නම් , එය එසේ විය යුතුය.

හැකි නම්, එහි STDIN හි ගොනු නාම සැකසීමට හැකිවීම find -print0 | smthසමඟ ප්‍රශස්ත විසඳුම වනු ඇත smth. smthලිපිගොනු කීයක් තිබුණත් ඔබට ඇත්තේ එක් ක්‍රියාවලියක් පමණි , තවද ඔබට ක්‍රියාවලි දෙක අතර බයිට් කුඩා ප්‍රමාණයක් (අභ්‍යන්තර නල බෆරින්ග් කුමක් සිදුවුවද) බෆර් කළ යුතුය. ඇත්ත වශයෙන්ම, මෙය smthසම්මත යුනික්ස් / පොසික්ස් විධානයක් නම් එය යථාර්ථවාදී නොවේ , නමුත් ඔබ එය ඔබම ලියන්නේ නම් ප්‍රවේශයක් විය හැකිය.

එය කළ නොහැකි find -print0 | xargs -0 smthනම්, වඩා හොඳ විසඳුමක් වනු ඇත. අදහස් දැක්වීමේදී @ dave_thompson_085 සඳහන් කර ඇති පරිදි, පද්ධති සීමාවන් කරා ළඟා වන විට (පෙරනිමියෙන්, 128 KB පරාසය තුළ හෝ පද්ධතිය මත පනවා ඇති ඕනෑම සීමාවක් තුළ) xargsබහුවිධ ලකුණු හරහා තර්ක බෙදී යයි , සහ කීදෙනෙකුට බලපෑම් කිරීමට විකල්ප තිබේද? ලිපිගොනු එක් ඇමතුමකට ලබා දී ඇති අතර එම නිසා ක්‍රියාවලි ගණන සහ ආරම්භක ප්‍රමාදය අතර තුලනයක් සොයා ගනී .smthexecsmthsmth

සංස්කරණය කරන්න: "හොඳම" යන සංකල්ප ඉවත් කර ඇත - වඩා හොඳ දෙයක් වර්ධනය වේ දැයි කීමට අපහසුය. ;)


find ... -exec smth {} +විසඳුමයි.
වයිල්ඩ්කාඩ්

1
find -print0 | xargs smthකිසිසේත් ක්‍රියා නොකරයි, නමුත් find -print0 | xargs -0 smth(සටහන -0) හෝ find | xargs smthලිපිගොනු වල හිස් අවකාශයක් නොමැති නම් හෝ බැක්ස්ලෑෂ් එකක් smthතිබේ නම් හැකි තරම් ගොනු නාමයන්ගෙන් එකක් ධාවනය වන අතර එක් තර්ක ලැයිස්තුවකට ගැලපේ ; ඔබ මැක්සාර්ග් ඉක්මවා ගියහොත්, smthලබා දී ඇති සියලුම තර්ක හැසිරවීමට අවශ්‍ය වාර ගණනක් එය ක්‍රියාත්මක වේ (සීමාවක් නැත). ඔබට කුඩා 'කුට්ටි' (තරමක් කලින් සමාන්තරකරණය) සමඟ සැකසිය හැකිය -L/--max-lines -n/--max-args -s/--max-chars.
dave_thompson_085


4

එක් හේතුවක් නම්, අවකාශය වැඩ වලදී ස්පැනරයක් විසි කිරීම, 'foo bar' ගොනුව 'foo' සහ 'bar' ලෙස ඇගයීමට ලක් කිරීමයි.

$ ls -l
-rw-rw-r-- 1 ec2-user ec2-user 0 Nov  7 18:24 foo bar
$ for file in `find . -type f` ; do echo filename $file ; done
filename ./foo
filename bar
$

-Exec ඒ වෙනුවට භාවිතා කරන්නේ නම් හොඳින් ක්‍රියා කරයි

$ find . -type f -exec echo filename {} \;
filename ./foo bar
$ find . -type f -exec stat {} \;
  File: ‘./foo bar’
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: ca01h/51713d    Inode: 9109        Links: 1
Access: (0664/-rw-rw-r--)  Uid: (  500/ec2-user)   Gid: (  500/ec2-user)
Access: 2016-11-07 18:24:42.027554752 +0000
Modify: 2016-11-07 18:24:42.027554752 +0000
Change: 2016-11-07 18:24:42.027554752 +0000
 Birth: -
$

විශේෂයෙන් findසෑම ගොනුවකම විධානයක් ක්‍රියාත්මක කිරීමට විකල්පයක් ඇති බැවින් එය හොඳම විකල්පයයි.
සෙන්ටිමන්

1
-exec ... {} \;එදිරිව සලකා බලන්න-exec ... {} +
thrig

1
ඔබ භාවිතා කරන්නේ නම් for file in "$(find . -type f)" සහ echo "${file}"එය හිස් අවකාශයන් සමඟ පවා ක්‍රියා කරයි නම්, මා අනුමාන කරන වෙනත් විශේෂ චරිත වඩාත් කරදර ඇති කරයි
mazs

9
@ මාස් - නැත, උපුටා දැක්වීම ඔබ සිතන දේ නොකරයි. ලිපිගොනු කිහිපයක් සහිත නාමාවලියක for file in "$(find . -type f)";do printf '%s %s\n' name: "${file}";done(ඔබට අනුව) එක් එක් ගොනු නාමය වෙනම පේළියක මුද්‍රණය කළ යුත්තේ කුමක් දැයි උත්සාහ කරන්න name:. එය එසේ නොවේ.
don_crissti

2

මන්ද ඕනෑම විධානයක ප්‍රතිදානය තනි නූලක් වන නමුත් ඔබේ ලූපයට පෙරළීමට නූල් පෙළක් අවශ්‍ය වේ. එය "ක්‍රියා කිරීමට" හේතුව, ෂෙල් වෙඩි ඔබ වෙනුවෙන් සුදු අවකාශයේ ඇති ද්‍රෝහී ලෙස බෙදීමයි.

දෙවනුව, ඔබට විශේෂ ලක්‍ෂණයක් අවශ්‍ය නොවන්නේ නම් find, ඔබේ කවචයට දැනටමත් පුනරාවර්තන ග්ලෝබ් රටාවක් තනිවම පුළුල් කළ හැකි බව මතක තබා ගන්න.

බෑෂ් උදාහරණය:

shopt -s nullglob globstar
for i in **
do
    echo «"$i"»
done

මාළු වල එකම:

for i in **
    echo «$i»
end

ඔබට එහි විශේෂාංග අවශ්‍ය නම් find, NUL මත පමණක් බෙදීමට වග බලා ගන්න ( find -print0 | xargs -r0idiom වැනි).

මසුන්ට NUL වෙන් කළ ප්‍රතිදානය නැවත ලබා ගත හැකිය. එබැවින් මෙය ඇත්තෙන්ම නරක නැත :

find -print0 | while read -z i
    echo «$i»
end

අවසාන ටිකක් gotcha ලෙස, බොහෝ ෂෙල් වෙඩි (මාළු ඇත්තෙන්ම නැත) දී, විධාන ප්රතිදානය කට ප්රහාරක කම්බියක් ශරීරය කිරීමට නියමිතව ඇත උප කබොළ (තේරුම ඔබ පුඩුවක් අවසන් කිරීමක් පසු පෙනෙන බව කිසිම ආකාරයකින් විචල්ය පිහිටුවා නැත හැක), වන කවදාවත් ඔබට අවශ්‍ය දේ.


@don_crissti හරියටම. එය සාමාන්‍යයෙන් ක්‍රියාත්මක නොවේ . මම උපහාසාත්මක වීමට උත්සාහ කළේ එය "ක්‍රියාත්මක" (උපුටා දැක්වීම් සහිතව) යැයි කියමිනි.
user2394284

පුනරාවර්තන ගෝලීයකරණය zsh90 දශකයේ මුල් භාගයේ ආරම්භ වූ බව සලකන්න (ඔබට **/*එහි අවශ්‍ය වුවද ). fishඩිරෙක්ටරි ගස බැස යන විට බාෂ්ගේ සමාන ලක්ෂණය කලින් ක්‍රියාත්මක කිරීම මෙන් සිම්ලින්ක් අනුගමනය කරයි. ක්‍රියාත්මක කිරීම් අතර ඇති වෙනස්කම් සඳහා ls *, ls ** සහ ls *** හි ප්‍රති result ලය බලන්න .
ස්ටෙෆාන් චසෙලාස්

1

සොයාගැනීම්වල ප්‍රතිදානය ලිවීම නරක පුරුද්දක් නොවේ bad නරක පුරුද්ද යනු කුමක්ද (මේ හා සියලු අවස්ථාවන්හිදී) ඔබේ ආදානය නිශ්චිත ආකෘතියක් බව දැන ගැනීම (පරීක්ෂා කිරීම සහ තහවුරු කිරීම) වෙනුවට විශේෂිත ආකෘතියක් යැයි උපකල්පනය කරයි.

tldr / cbf: find | parallel stuff


0

සොයාගැනීමෙන් ආපසු ලබා දෙන එක් එක් ගොනුවේ නම / මාර්ගය සඳහා විධාන එකක් හෝ කිහිපයක් ක්‍රියාත්මක කිරීමට සුදුසුම ක්‍රමය කුමක්ද?

මම zsh භාවිතා කරමින් මැක් එකක සිටිමි. Fd විධානයේ (පයිප්ප සිට fzf දක්වා) ප්‍රති a ල අරාවකට ලබා ගන්නේ කෙසේදැයි සොයමින් සිටියදී මට මෙම ප්‍රශ්නය හමු විය. ගොනු නාමවල ඇති අවකාශයන් වෙනම අංග ලෙස ගබඩා කර තිබීම ගැන මට කරදර විය යුතු නැති ආකාරයකින්. මෙම අරාව සමඟ මම එම ගොනු නම් එකවර වෙනත් ස්ක්‍රිප්ට් එකකට යවනවා.

මම ස්ටෙෆේන්ගේ පිළිතුරට ඡන්දය දීමට උත්සාහ කළේ එය මගේ පිළිතුර සොයා ගැනීමට අවශ්‍ය තොරතුරු ලබා දුන් නිසාය - මෙය මට භාවිතා කිරීම සඳහා:

array_name=(${(0)"$(fd "\.tar\.gz$|\.tgz$|\.zip$|\.tar.bz2|\.tar$" | fzf --print0)"})

($ {(0) ...}) කෑල්ල කරන්නේ කුමක්දැයි මම වඩා හොඳින් තේරුම් ගත යුතුය. සමහර විට එය භාවිතා කිරීමට නොහැකි වීම පෙන්වා දීම සමඟ බැඳී ඇත IFS=$'\0'. මම ඉක්මන් සෙවීමක් කිරීමට උත්සාහ කළ අතර මට සොයාගත හැකි වූයේ \ 0 සම්බන්ධයෙනි. මම එය මෙහි සොයාගත්තා: පුළුල් කිරීම පිළිබඳ zsh ප්‍රලේඛනයේ , එහි සඳහන් වන්නේ:

14.3.1 පරාමිති පුළුල් කිරීමේ කොඩි

ආරම්භක වරහන සෘජුවම ආරම්භක වරහන් මගින් අනුගමනය කරන්නේ නම්, ගැලපෙන සංවෘත වරහන් දක්වා ඇති නූල කොඩි ලැයිස්තුවක් ලෙස ගනු ලැබේ. ධජයක් පුනරාවර්තනය කිරීම අර්ථවත් වන අවස්ථා වලදී, පුනරාවර්තන අඛණ්ඩව සිදු නොවිය යුතුය; උදාහරණයක් ලෙස, ' (q%q%q)' යන්නෙන් කියවිය හැක්කේ වඩා කියවිය හැකි දෙයයි (%%qqq). පහත දැක්වෙන කොඩි සඳහා සහය දක්වයි:

[...]
0
පුළුල් කිරීමේ ප්‍රති result ලය ශුන්‍ය බයිට් මත බෙදන්න. මෙය ' ps:\0:' සඳහා වූ කෙටි යෙදුමකි .

සොයාගැනීමේ ප්‍රතිදානය නරක අතට හැරෙන්නේ ඇයි?

වසර කිහිපයක බැෂ් ස්ක්‍රිප්ටින් කිරීමෙන් පසුව පවා ඒ පිළිබඳව ඔබට උපදෙස් ලබා දිය යුතු අවසාන පුද්ගලයා මමයි. :) නමුත් මම අඩුවෙන් කිරීමට උත්සාහ කර ඇත්තේ විචල්‍යයකට rc විධානයකින් දමා විචල්‍යය පරීක්ෂා කිරීමයි. ඒ වෙනුවට මම උත්සාහ කරන්නේ නම් සහ භාවිතා කරන්නේ නම්:

if echo “${something}” | grep '^s’ -q; then {
:
} elif [[ $(dirname \""${file}\"") == "." ]]; then {

මෙය ඔබට / යමෙකුට උපකාරී වනු ඇතැයි මම බලාපොරොත්තු වෙමි.



-2

සොයාගැනීම්වල ප්‍රතිදානය ලිවීම බොහෝ විට නරක පුරුද්දකි, විශේෂයෙන් පොදු අරමුණු සහිත ස්ක්‍රිප්ට් සමඟ, ඔබ තත්වයන් ගැන වැඩි යමක් නොදන්නා විට එය භාවිතා වේ.

මගේ දෛනික වැඩ කටයුතුවලදී, බොහෝ විට එක් උප බහලුමකට පහළින් ඇති ලිපිගොනු පිළිබඳ දැනුමක් මා සතුව ඇත. තවද මම කිසි විටෙකත් හිස්, නව රේඛා, ටැබ් සහ ඒවායේ නම් සහිත ගොනු නාමයන් තනිවම භාවිතා නොකරමි. එය මුලින් ම නරක අදහසක්, ගැටළු ඉල්ලා සිටීම.

උදාහරණයක් ලෙස, මගේ කැමරාවෙන් පින්තූර හැකිලීමට මට පිටපතක් ඇත, ඒවා සාමාන්‍ය ඒවා වන අතර කිසි විටෙකත් වෙනස් නොවේ. ඔවුන්ගේ මාවතේ හිස් තැන් හෝ ගොනු නාම අඩංගු නොවේ. (IMG00001.JPG) මට නව කැමරාවක් ලැබෙන්නේ නම්, මට පිටපත වෙනස් කිරීමට අවශ්‍ය වනු ඇත.

තාවකාලික විධාන සඳහා, නිකුත් කර අමතක කර ඇති විට එය ගැටළුවක් නොවේ. තනි පරිශීලක යන්ත්‍ර සඳහා, ඔබ ඔබේ කේතය බෙදා නොගන්නේ නම්, එය ද ගැටළුවක් නොවිය යුතුය.

SO පිළිබඳ උපදෙස් ලබා දෙන විට, ඔබ කරන අන්තරායන් සහ උපකල්පන සන්නිවේදනය නොකිරීම බොහෝ විට ගැටළුවක් වේ, මන්ද අනෙක් පුද්ගලයින්ට විෂ සහිත ගොනු නාමයක් තිබිය හැකි බැවිනි.

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.