මගේ ෂෙල් ස්ක්‍රිප්ට් හිස් අවකාශයේ හෝ වෙනත් විශේෂ අක්ෂරවලින් යටපත් වන්නේ ඇයි?


300

නැතහොත්, ශක්තිමත් ගොනු නාම හැසිරවීම සහ ෂෙල් ස්ක්‍රිප්ට් තුළ වෙනත් නූල් සම්මත කිරීම සඳහා හඳුන්වාදීමේ මාර්ගෝපදේශයකි.

මම ෂෙල් ස්ක්‍රිප්ට් එකක් ලිව්වා. නමුත් එය සමහර යෙදවුම් මත යටපත් වේ (උදා: සමහර ගොනු නම් මත).

මට පහත සඳහන් ගැටලුව වැනි ගැටලුවකට මුහුණ දීමට සිදු විය:

  • මම ඉඩක් අඩංගු ගොනු නාමය ඇති hello worldඅතර, එය ගොනු වෙනම දෙකක් ලෙස සලකනු ලැබූ helloසහ world.
  • මට අඛණ්ඩ අවකාශ දෙකක් සහිත ආදාන රේඛාවක් ඇති අතර ඒවා ආදානයේ එකකට හැකිලී ගියේය.
  • ආදාන රේඛාවලින් ප්‍රමුඛ හා පසුපස සුදු අවකාශය අතුරුදහන් වේ.
  • සමහර විට, ආදානයේ එක් අක්ෂරයක් අඩංගු වූ විට \[*?, ඒවා සමහර පෙළ මගින් ප්‍රතිස්ථාපනය කරනු ලැබේ, එය ඇත්ත වශයෙන්ම ලිපිගොනු වල නම වේ.
  • ආදානයේ අපෝස්තලාපයක් '(හෝ ද්විත්ව උපුටා දැක්වීමක් ") ඇති අතර, එම ලක්ෂ්‍යයෙන් පසුව දේවල් අමුතු විය.
  • ආදානයේ බැක්ස්ලෑෂ් පවතී (හෝ: මම සිග්වින් භාවිතා කරන අතර මගේ සමහර ගොනු නම් වින්ඩෝස් විලාසිතාවේ \බෙදුම්කරුවන් ඇත).

සිදුවන්නේ කුමක්ද සහ එය නිවැරදි කරන්නේ කෙසේද?


20
shellcheckඔබේ වැඩසටහන් වල ගුණාත්මකභාවය වැඩි දියුණු කිරීමට ඔබට උපකාරී වේ.
aurelien

3
පිළිතුරු වල විස්තර කර ඇති ආරක්ෂණ ක්‍රමවේදයන්ට අමතරව, එය බොහෝ පා readers කයන්ට පැහැදිලිව පෙනෙන්නට තිබුණද, විධාන රේඛා මෙවලම් භාවිතයෙන් ලිපිගොනු සැකසීමට අදහස් කරන විට, විසිතුරු අක්ෂර වලින් වැළකී සිටීම හොඳ පුරුද්දක් බව මම සිතමි. හැකි නම් පළමු ස්ථානයේ නම්.
bli


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

පළමුවෙන්ම, ඔබේ පරාමිතීන් අවකාශයන් තිබේ නම් ඒවා ඇතුළට යාම (විධාන රේඛාවේ) සඳහන් කළ යුතුය. කෙසේ වෙතත් ඔබට සම්පූර්ණ විධාන රේඛාවම අල්ලා එය විග්‍රහ කළ හැකිය. අවකාශ දෙකක් එක් අවකාශයකට හැරෙන්නේ නැත; ඕනෑම ඉඩ ප්‍රමාණයක් ඔබගේ ස්ක්‍රිප්ටයට ඊළඟ විචල්‍යය යැයි කියනු ඇත, එබැවින් ඔබ "echo $ 1 $ 2" වැනි දෙයක් කරන්නේ නම් එය ඔබගේ ස්ක්‍රිප්ට් එක අතර එක් ඉඩක් තබයි. ලූපයක් සඳහා නොව අවකාශයන් සහිත ලිපිගොනු නැවත සැකසීමට "සොයන්න (-exec)" භාවිතා කරන්න; ඔබට අවකාශයන් සමඟ වඩාත් පහසුවෙන් ගනුදෙනු කළ හැකිය.
පැට්‍රික් ටේලර්

Answers:


372

විචල්ය ආෙද්ශක සහ විධාන ආෙද්ශක පමණ, උද්ධෘත පාඨ සෑම විටම භාවිතා කරන්න: "$foo","$(foo)"

ඔබ $fooනොකැඩූ ලෙස භාවිතා කරන්නේ නම් , ඔබේ ස්ක්‍රිප්ට් $(foo)සුදු අවකාශය අඩංගු ආදාන හෝ පරාමිතීන් (හෝ විධාන ප්‍රතිදානය සමඟ ) යටපත් කරයි \[*?.

එහිදී ඔබට කියවීම නැවැත්විය හැකිය. හොඳයි, හරි, මෙන්න තවත් කිහිපයක්:

  • read- බිල්ඩින් සමඟ පේළි අනුව ආදාන රේඛාව කියවීම සඳහා read,while IFS= read -r line; do …
    ප්ලේන් readට්‍රීට්ස් බැක්ස්ලෑෂ් සහ වයිට්ස්පේස් විශේෂයෙන් භාවිතා කරන්න.
  • xargs- වළකින්නxargs . ඔබ භාවිතා කළ යුතු නම් xargs, එය සාදන්න xargs -0. ඒ වෙනුවට find … | xargs, කැමති වන්නfind … -exec … .
    xargsහිස් අවකාශය සහ චරිත \"'විශේෂයෙන් සලකයි .

මේ පිළිතුර Bourne / POSIX ආකාරයේ ෂෙල් වෙඩි අදාළ ( sh, ash, dash, bash, ksh, mksh, yash....) Zsh භාවිතා කරන්නන් එය මඟ හැරිය යුතු අතර ද්විත්ව උපුටා දැක්වීම අවශ්‍ය වන්නේ කවදාද? වෙනුවට. ඔබට සම්පූර්ණ අවශ්‍යතාවය අවශ්‍ය නම්, සම්මත හෝ ඔබේ කවචයේ අත්පොත කියවන්න.


පහත දැක්වෙන පැහැදිලි කිරීම්වල දළ වශයෙන් ස්වල්පයක් අඩංගු බව සලකන්න (බොහෝ තත්වයන් තුළ සත්‍ය වන නමුත් අවට සන්දර්භය හෝ වින්‍යාසය මගින් බලපෑම් කළ හැකි ප්‍රකාශ).

මට ලිවීමට අවශ්‍ය ඇයි "$foo"? උපුටා දැක්වීම් නොමැතිව කුමක් සිදුවේද?

$foo“විචල්‍යයේ අගය ගන්න” යන්නෙන් අදහස් නොවේ foo. එයින් අදහස් කරන්නේ වඩා සංකීර්ණ දෙයක්:

  • පළමුව, විචල්යයේ අගය ගන්න.
  • ක්ෂේත්‍ර බෙදීම: එම අගය හිස් අවකාශයකින් වෙන් කළ ක්ෂේත්‍ර ලැයිස්තුවක් ලෙස සලකන්න, එහි ප්‍රති ing ලයක් ලෙස ලැයිස්තුව සාදන්න. උදාහරණයක් ලෙස, විචල්ය අඩංගු නම් foo * bar ​එවිට මෙම පියවර ප්රතිඵලයක් 3-අංගයක් ලැයිස්තුව foo, *, bar.
  • ගොනු නාම උත්පාදනය: සෑම ක්ෂේත්‍රයක්ම ගෝලීය ලෙස සලකන්න, එනම් ආදේශක රටාවක් ලෙස සලකන්න, සහ මෙම රටාවට ගැලපෙන ගොනු නාම ලැයිස්තුවෙන් එය ප්‍රතිස්ථාපනය කරන්න. රටාව කිසිදු ලිපිගොනුවකට නොගැලපේ නම්, එය නවීකරණය නොකෙරේ. අපගේ උදාහරණයේ දී, මෙහි ප්‍රති results fooලය වනුයේ වත්මන් නාමාවලියෙහි ඇති ගොනු ලැයිස්තුවෙන් පසුව, අවසානයේ අඩංගු වන ලැයිස්තුවයි bar. වත්මන් බහාළුම හිස් නම්, එහි ප්රතිඵලය වන්නේ foo, *, bar.

ප්‍රති result ලය නූල් ලැයිස්තුවක් බව සලකන්න. ෂෙල් සින්ටැක්ස් හි සන්දර්භ දෙකක් ඇත: ලැයිස්තු සන්දර්භය සහ නූල් සන්දර්භය. ක්ෂේත්‍ර බෙදීම් සහ ගොනු නාම උත්පාදනය සිදුවන්නේ ලැයිස්තු සන්දර්භය තුළ පමණි, නමුත් එය බොහෝ විට සිදු වේ. ද්විත්ව උපුටා දැක්වීම් නූල් සන්දර්භයක් සීමා කරයි: මුළු ද්විත්ව-උපුටා ගත් නූල බෙදීමට නොයන තනි නූලකි. (ව්‍යතිරේකය: "$@"ස්ථානීය පරාමිති ලැයිස්තුවට ව්‍යාප්ත කිරීම සඳහා, උදා: ස්ථානීය පරාමිතීන් තුනක් "$@"තිබේ "$1" "$2" "$3"නම් එය සමාන වේ . බලන්න $ * සහ $ between අතර වෙනස කුමක්ද? )

විධාන ආදේශ කිරීම සමඟ $(foo)හෝ සමඟ සිදු `foo`වේ. පැත්තක සටහනක, භාවිතා නොකරන්න `foo`: එහි උපුටා දැක්වීමේ නීති අමුතු හා අතේ ගෙන යා නොහැකි ඒවා වන අතර, නවීන ෂෙල් වෙඩි සඳහා සහය දක්වන්නේ $(foo)බුද්ධිමය උපුටා දැක්වීමේ නීති හැරෙන්නට නියත වශයෙන්ම සමාන වේ.

අංක ගණිත ආදේශනයේ ප්‍රතිදානය ද එකම ප්‍රසාරණයකට භාජනය වේ, නමුත් එය සාමාන්‍යයෙන් සැලකිලිමත් වන්නේ එය පුළුල් කළ නොහැකි අක්ෂර පමණක් අඩංගු වන හෙයිනි ( IFSඉලක්කම් හෝ නැතැයි උපකල්පනය කරයි -).

බලන්න අවශ්ය ද්විත්ව උපුටා දක්වමින් විට? ඔබට උපුටා දැක්වීම් අතහැර දැමිය හැකි අවස්ථා පිළිබඳ වැඩි විස්තර සඳහා.

මේ සියලු රිග්මරෝලය සිදුවීමට ඔබ අදහස් නොකරන්නේ නම්, සෑම විටම විචල්ය සහ විධාන ආදේශක වටා ද්විත්ව මිල ගණන් භාවිතා කිරීමට මතක තබා ගන්න. සැලකිලිමත් වන්න: උපුටා දැක්වීම් පිටවීම දෝෂ වලට පමණක් නොව ආරක්ෂක වළලු වලට ද හේතු විය හැක .

ගොනු නාම ලැයිස්තුවක් සකසන්නේ කෙසේද?

myfiles="file1 file2"ලිපිගොනු වෙන් කිරීම සඳහා අවකාශයන් සමඟ ඔබ ලියන්නේ නම් , මෙය හිස් අවකාශයන් සහිත ගොනු නම් සමඟ ක්‍රියා කළ නොහැක. යුනික්ස් ලිපිගොනු නාමවල /(සෑම විටම නාමාවලි බෙදුම්කරුවෙකු වන) සහ ශුන්‍ය බයිට් (ඔබට බොහෝ ෂෙල් වෙඩි ඇති ෂෙල් ස්ක්‍රිප්ට් වල භාවිතා කළ නොහැකි) හැර වෙනත් අක්ෂර අඩංගු විය හැකිය .

එකම ගැටලුව myfiles=*.txt; … process $myfiles. ඔබ මෙය කරන විට, විචල්යයේ myfilesඅක්ෂර 5 කින් යුත් නූලක් අඩංගු වන අතර *.txt, ඔබ ලියන $myfilesවිට ආදේශක කාඩ්පත පුළුල් වේ. ඔබ ඔබේ ස්ක්‍රිප්ට් එක වෙනස් කරන තුරු මෙම උදාහරණය සැබවින්ම ක්‍රියාත්මක myfiles="$someprefix*.txt"; … process $myfilesවේ. someprefixසකසා ඇත්නම් final report, මෙය ක්‍රියා නොකරනු ඇත.

ඕනෑම ආකාරයක ලැයිස්තුවක් සැකසීමට (ගොනු නාම වැනි), එය අරාවකට දමන්න. මේ සඳහා mksh, ksh93, yash හෝ bash (හෝ zsh, මේ සියලු උපුටා දැක්වීමේ ගැටළු නොමැති) අවශ්‍ය වේ; සරල POSIX කවචයකට (අළු හෝ ඉරක් වැනි) අරාව විචල්‍යයන් නොමැත.

myfiles=("$someprefix"*.txt)
process "${myfiles[@]}"

Ksh88 හි වෙනස් පැවරුම් සින්ටැක්ස් සහිත අරාව විචල්‍යයන් ඇත set -A myfiles "someprefix"*.txt( ඔබට ksh88 / bash portability අවශ්‍ය නම් විවිධ ksh පරිසරය යටතේ පැවරුම් විචල්‍යය බලන්න ). බෝර්න් / පොසික්ස් විලාසිතාවේ ෂෙල් වෙඩි සඳහා තනි අරා එකක් ඇත, "$@"ඔබ පිහිටුවා ඇති ස්ථානීය පරාමිතීන් සමූහයක් setසහ ශ්‍රිතයකට දේශීය වේ:

set -- "$someprefix"*.txt
process -- "$@"

ආරම්භ වන ගොනු නාම ගැන කුමක් කිව -හැකිද?

ආශ්‍රිත සටහනක, ගොනු නාමයන් -(ඩෑෂ් / us ණ) සමඟ ආරම්භ කළ හැකි බව මතක තබා ගන්න, බොහෝ විධානයන් අර්ථ නිරූපණය කරන්නේ විකල්පයක් ලෙසය. සමහර විධානයන් (වැනි sh, setහෝ sort) ආරම්භ වන විකල්ප පිළිගනී +. ඔබට විචල්ය කොටසකින් ආරම්භ වන ගොනු නාමයක් තිබේ --නම්, ඉහත ස්නිපටයේ මෙන් එය පෙර සම්මත කිරීමට වග බලා ගන්න . මෙය විකල්පයේ අවසානයට ළඟා වී ඇති බවට විධානයට ඇඟවුම් කරයි, එබැවින් ඉන් පසුව ඕනෑම දෙයක් ගොනු නාමයක් වන අතර එය ආරම්භ වුවද -හෝ +වේ.

විකල්පයක් ලෙස, ඔබේ ගොනු නාම හැර වෙනත් අක්ෂරයකින් ආරම්භ වන බවට ඔබට සහතික විය හැකිය -. නිරපේක්ෂ ගොනු නාම වලින් ආරම්භ /වන අතර ඔබට ./සාපේක්ෂ නම් ආරම්භයේදී එකතු කළ හැකිය . පහත දැක්වෙන ස්නිපටය මඟින් විචල්යයේ අන්තර්ගතය fආරම්භ කිරීම -හෝ නොකිරීම සහතික කරන එකම ගොනුව වෙත යොමු කිරීමේ “ආරක්ෂිත” ක්‍රමයක් බවට පත් කරයි +.

case "$f" in -* | +*) "f=./$f";; esac

මෙම මාතෘකාව පිළිබඳ අවසාන සටහනක, සමහර විධානයන් -සම්මත ආදානය හෝ සම්මත ප්‍රතිදානය ලෙස අර්ථකථනය කරන බවට පරිස්සම් වන්න --. ඔබට නම් කරන ලද සත්‍ය ගොනුවක් වෙත යොමු වීමට අවශ්‍ය නම් -, හෝ ඔබ එවැනි වැඩසටහනක් අමතන්නේ නම් සහ එය stdin වෙතින් කියවීමට හෝ stdout වෙත ලිවීමට ඔබට අවශ්‍ය නැතිනම්, -ඉහත පරිදි නැවත ලිවීමට වග බලා ගන්න . බලන්න "du -sh *" සහ "du -sh ./*" අතර වෙනස කුමක්ද? වැඩිදුර සාකච්ඡා සඳහා.

විචල්‍යයක විධානයක් ගබඩා කරන්නේ කෙසේද?

“විධානය” යන්නට කරුණු තුනක් අදහස් කළ හැකිය: විධාන නාමයක් (ක්‍රියාත්මක කළ හැකි නමක්, සම්පූර්ණ මාර්ගයක් සහිතව හෝ රහිතව, හෝ ශ්‍රිතයක නම, බිල්ඩින් හෝ අන්වර්ථය), තර්ක සහිත විධාන නාමයක් හෝ ෂෙල් කේතයක්. ඒ අනුව ඒවා විචල්‍යයක ගබඩා කිරීමේ විවිධ ක්‍රම තිබේ.

ඔබට විධාන නමක් තිබේ නම්, එය ගබඩා කර සුපුරුදු පරිදි ද්විත්ව උපුටා දැක්වීම් සහිත විචල්‍යය භාවිතා කරන්න.

command_path="$1"

"$command_path" --option --message="hello world"

ඔබට තර්ක සහිත විධානයක් තිබේ නම්, ගැටළුව ඉහත ගොනු නාම ලැයිස්තුවක් හා සමාන වේ: මෙය නූල් ලැයිස්තුවක් මිස නූලක් නොවේ. ඔබට තර්ක අතර ඇති අවකාශයන් සහිත තනි නූලකට දැමිය නොහැක, මන්ද ඔබ එසේ කරන්නේ නම්, තර්කවල කොටසක් වන අවකාශයන් සහ තර්ක වෙන් කරන අවකාශයන් අතර වෙනස ඔබට කිව නොහැක. ඔබේ කවචයේ අරා තිබේ නම්, ඔබට ඒවා භාවිතා කළ හැකිය.

cmd=(/path/to/executable --option --message="hello world" --)
cmd=("${cmd[@]}" "$file1" "$file2")
"${cmd[@]}"

ඔබ අරා නොමැතිව කවචයක් භාවිතා කරන්නේ නම් කුමක් කළ යුතුද? ස්ථානීය පරාමිතීන් වෙනස් කිරීමට ඔබට අවශ්‍ය නැතිනම් ඔබට තවමත් ස්ථානීය පරාමිතීන් භාවිතා කළ හැකිය.

set -- /path/to/executable --option --message="hello world" --
set -- "$@" "$file1" "$file2"
"$@"

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

code='/path/to/executable --option --message="hello world" -- /path/to/file1 | grep "interesting stuff"'
eval "$code"

අර්ථ දැක්වීමේදී කැදැලි උපුටා දැක්වීම් සැලකිල්ලට ගන්න code: තනි උපුටා දැක්වීම් '…'වචනාර්ථයෙන් සීමා කරයි, එවිට විචල්‍යයේ අගය codeනූල් /path/to/executable --option --message="hello world" -- /path/to/file1වේ. මෙම evalbuiltin එසේ එම අවස්ථාවේ දී මේ ආකාරයටම හා නළ මාර්ග, කියවූ ඇත ආදිය, එය කේත රචනය තුල පෙනී නම් කරන තර්කයක් ලෙස සම්මත වැල විග්රහ කළ කිරීමට ෂෙල් කියයි

භාවිතා evalකිරීම උපක්‍රමශීලී ය. විග්‍රහ කරන විට කුමක් සිදුවේදැයි හොඳින් සිතා බලන්න. විශේෂයෙන්, ඔබට ගොනුවේ නමක් කේතයට ඇතුළත් කළ නොහැක: ඔබ එය උපුටා දැක්විය යුතුය, එය ප්‍රභව කේත ගොනුවක තිබුනාක් මෙන්. එය කිරීමට සෘජු ක්‍රමයක් නොමැත. වගේ දෙයක් code="$code $filename"ගොනු නම නම් විරාම ඕනෑම ෂෙල් විශේෂ චරිතයක් (හිස් තැන්, අඩංගු වේ $, ;, |, <, >, ආදිය). code="$code \"$filename\""තවමත් කැඩී යයි "$\`. පවා code="$code '$filename'"විරාම ගොනු නම අඩංගු නම් '. විසඳුම් දෙකක් තිබේ.

  • ගොනු නාමය වටා උපුටා දැක්වීම් තට්ටුවක් එක් කරන්න. එය කිරීමට ඇති පහසුම ක්‍රමය නම් එය වටා තනි උපුටා දැක්වීම් එකතු කිරීම සහ තනි උපුටා දැක්වීම් ආදේශ කිරීම ය '\''.

    quoted_filename=$(printf %s. "$filename" | sed "s/'/'\\\\''/g")
    code="$code '${quoted_filename%.}'"
  • කේතය තුළ විචල්‍ය ප්‍රසාරණය තබා ගන්න, එවිට එය කේතය ඇගයීමට ලක් කරන විට මිස කේත කැබැල්ල ගොඩනඟන විට නොවේ. මෙය වඩාත් සරල නමුත් ක්‍රියාත්මක වන්නේ කේතය ක්‍රියාත්මක කරන අවස්ථාවේ විචල්‍යය එකම අගයක් සහිතව පවතී නම් පමණි, උදා: කේතය ලූපයකින් සාදා ඇත්නම් නොවේ.

    code="$code \"\$filename\""

අවසාන වශයෙන්, ඔබට ඇත්ත වශයෙන්ම කේත අඩංගු විචල්‍යයක් අවශ්‍යද? කේත කොටසකට නමක් ලබා දිය හැකි වඩාත් ස්වාභාවික ක්‍රමය නම් ශ්‍රිතයක් අර්ථ දැක්වීම ය.

මොකද readවෙන්නේ?

නොමැතිව -r, readඅඛණ්ඩ රේඛා වලට ඉඩ දෙයි - මෙය තනි තාර්කික ආදාන රේඛාවකි:

hello \
world

readආදාන රේඛාව අක්ෂර වලින් වෙන් කරන ලද ක්ෂේත්‍ර වලට බෙදයි $IFS(නොමැතිව -r, බැක්ස්ලෑෂ් ද ඒවායින් ගැලවී යයි). උදාහරණයක් ලෙස, ආදාන වචන තුන අඩංගු රේඛාවක් වේ නම්, එවිට read first second thirdසකසයි firstආදාන පළමු වචනය, secondදෙවන වචනයක් හා thirdතෙවන වචනය. තවත් වචන තිබේ නම්, අවසාන විචල්‍යයෙහි පෙර වචන සැකසීමෙන් පසු ඉතිරිව ඇති සියල්ල අඩංගු වේ. ප්‍රමුඛ හා පසුපස සුදු අවකාශය කපා ඇත.

IFSහිස් නූලට සැකසීම කිසිදු කැපීමක් වළක්වයි. `IFS = වෙනුවට IFS = කියවීම` නිතර භාවිතා කරන්නේ ඇයිදැයි බලන්න ; කියවන අතරතුර..`? දිගු පැහැදිලි කිරීමක් සඳහා.

මොකක්ද වැරැද්ද xargs?

ආදාන ආකෘතිය xargsසුදු අවකාශයෙන් වෙන් කරන ලද නූල් වන අතර එය විකල්ප වශයෙන් තනි හෝ ද්විත්ව උපුටා දැක්විය හැකිය. සම්මත මෙවලමක් මෙම ආකෘතිය ප්‍රතිදානය නොකරයි.

ආදානය රේඛා ලැයිස්තුවක් xargs -L1හෝ xargs -lපාහේ වේ, නමුත් එතරම් නොවේ - රේඛාවක අවසානයේ ඉඩක් තිබේ නම්, පහත දැක්වෙන රේඛාව අඛණ්ඩ රේඛාවකි.

ඔබට xargs -0අදාළ තැන භාවිතා කළ හැකිය (සහ ලබා ගත හැකි ස්ථාන: ග්නූ (ලිනක්ස්, සිග්වින්), බුසි බොක්ස්, බීඑස්ඩී, ඕඑස්එක්ස්, නමුත් එය පොසික්ස් හි නොමැත). එය ආරක්ෂිතයි, මන්ද බොහෝ දත්ත වල, විශේෂයෙන් ගොනු නාමවල ශුන්‍ය බයිට් දර්ශණය විය නොහැක. ශුන්‍යයෙන් වෙන් කරන ලද ගොනු නාම ලැයිස්තුවක් නිෂ්පාදනය කිරීම සඳහා, භාවිතා කරන්න find … -print0(නැතහොත් find … -exec …පහත විස්තර කර ඇති පරිදි ඔබට භාවිතා කළ හැකිය ).

සොයාගත් ලිපිගොනු සකසන්නේ findකෙසේද?

find  -exec some_command a_parameter another_parameter {} +

some_commandබාහිර විධානයක් විය යුතුය, එය ෂෙල් ශ්‍රිතයක් හෝ අන්වර්ථයක් විය නොහැක. ලිපිගොනු සැකසීමට ඔබට කවචයක් කැඳවීමට අවශ්‍ය නම්, shපැහැදිලිව අමතන්න .

find  -exec sh -c '
  for x do
    … # process the file "$x"
  done
' find-sh {} +

මට තවත් ප්‍රශ්නයක් තිබේ

මෙම වෙබ් අඩවියේ ටැගය බ්‍රවුස් කරන්න , නැතහොත් හෝ . (සාමාන්‍ය ඉඟි කිහිපයක් සහ අතින් තෝරාගත් පොදු ප්‍රශ්න ලැයිස්තුවක් බැලීමට “වැඩිදුර ඉගෙන ගන්න…” මත ක්ලික් කරන්න.) ඔබ සෙවූ නමුත් ඔබට පිළිතුරක් සොයාගත නොහැකි නම්, ඉවතට යන්න .


6
10 John1024 එය GNU ලක්ෂණයකි, එබැවින් මම “සම්මත මෙවලමක්” නොමැතිව සිටිමි.
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

2
ඔබ ද පමණ මිල කැඳවීම් අවශ්ය $(( ... ))(ද $[...]හැර සමහර කවච) zsh(පවා sh රූප රචනයක් දී) සහ mksh.
ස්ටෙෆාන් චසෙලාස්

3
xargs -0POSIX නොවන බව සලකන්න . FreeBSD හැර xargs, ඔබට සාමාන්‍යයෙන් අවශ්‍ය වන්නේ xargs -r0ඒ වෙනුවට ය xargs -0.
ස්ටෙෆාන් චසෙලාස්

2
10 ජෝන් 1024, නැත, ls --quoting-style=shell-alwaysනොගැලපේ xargs. උත්සාහ කරන්නtouch $'a\nb'; ls --quoting-style=shell-always | xargs
ස්ටෙෆාන් චසෙලාස්

3
තවත් ලස්සන (GNU-පමණි) පහසුකම, xargs -d "\n"ඔබ උදා ක්රියාත්මක කළ හැකි වන පරිදි locate PATTERN1 |xargs -d "\n" grep PATTERN2ගැලපෙන ගොනුව නම් සෙවීමට PATTERN1 අන්තර්ගතයට ගැලපෙන සමග PATTERN2 . GNU තොරව, ඔබ උදා වැනි ඒක කරන්න පුළුවන්locate PATTERN1 |perl -pne 's/\n/\0/' |xargs -0 grep PATTERN1
ආදම් කාට්ස්

26

ගිලෙස්ගේ පිළිතුර විශිෂ්ට වුවත්, මම ඔහුගේ ප්‍රධාන කාරණය සලකා බලමි

විචල්ය ආදේශක සහ විධාන ආදේශක වටා සෑම විටම ද්විත්ව මිල ගණන් භාවිතා කරන්න: "$ foo", "$ (foo)"

ඔබ වචන බෙදීම් කරන බාෂ් වැනි කවචයකින් ආරම්භ කරන විට, ඔව්, ආරක්ෂිත උපදෙස් සෑම විටම උපුටා දැක්වීම් භාවිතා කරයි. කෙසේ වෙතත් වචන බෙදීම සැමවිටම සිදු නොවේ

§ වචන බෙදීම

මෙම විධානයන් දෝෂයකින් තොරව ක්‍රියාත්මක කළ හැකිය

foo=$bar
bar=$(a command)
logfile=$logdir/foo-$(date +%Y%m%d)
PATH=/usr/local/bin:$PATH ./myscript
case $foo in bar) echo bar ;; baz) echo baz ;; esac

මෙම හැසිරීම අනුගමනය කිරීමට මම පරිශීලකයින් දිරිමත් නොකරමි, නමුත් වචන බෙදීමක් සිදුවන විට යමෙකු තදින් වටහා ගන්නේ නම්, උපුටා දැක්වීම් භාවිතා කළ යුත්තේ කවදාදැයි තීරණය කිරීමට ඔවුන්ට හැකි විය යුතුය.


20
මගේ පිළිතුරෙහි මා සඳහන් කරන පරිදි, විස්තර සඳහා unix.stackexchange.com/questions/68694/… බලන්න. “මගේ ෂෙල් පිටපත යටපත් වන්නේ ඇයි?” යන ප්‍රශ්නය සැලකිල්ලට ගන්න. වඩාත්ම පොදු ගැටළුව (මෙම වෙබ් අඩවියේ සහ වෙනත් තැන්වල වසර ගණනාවක අත්දැකීම් වලින්) ද්විත්ව උපුටා දැක්වීම් නොමැත. “සැමවිටම ද්විත්ව උපුටා දැක්වීම් භාවිතා කිරීම” මතක තබා ගැනීම පහසුය, “සෑම විටම ද්විත්ව උපුටා දැක්වීම් භාවිතා කරන්න, ඒවා අවශ්‍ය නොවන අවස්ථා හැර”.
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

14
ආරම්භකයින් සඳහා නීති තේරුම් ගැනීමට අපහසුය. උදාහරණයක් වශයෙන්, foo=$barහරි, නමුත් export foo=$barහෝ env foo=$var(අවම වශයෙන් සමහර කවච) නොවේ. ආරම්භකයා සඳහා උපදෙස්: ඔබ කරන්නේ කුමක්දැයි ඔබ නොදන්නේ නම් සහ එසේ නොකිරීමට හොඳ හේතුවක් නොමැති නම් සෑම විටම ඔබේ විචල්‍යයන් උපුටා දක්වන්න .
ස්ටෙෆාන් චසෙලාස්

6
Te ස්ටීවන්පෙනී එය වඩාත් නිවැරදිද? උපුටා දැක්වීම් පිටපත බිඳ දැමිය හැකි සාධාරණ අවස්ථා තිබේද? අවස්ථා වලදී උපුටා දැක්වීම් භාවිතා කළ යුතු අවස්ථා වලදී සහ අනෙක් අර්ධ උපුටා දැක්වීම් විකල්ප ලෙස භාවිතා කළ හැකිය - එවිට “සෑම විටම උපුටා දැක්වීම් භාවිතා කරන්න” යන නිර්දේශය සිතා බැලිය යුතු කරුණකි, එය සත්‍ය, සරල හා අඩු අවදානම් සහිත බැවින්. ආරම්භකයින්ට එවැනි ව්‍යතිරේක ලැයිස්තු ඉගැන්වීම අකාර්යක්ෂම බව (සන්දර්භය නොමැති වීම, ඔවුන් ඒවා මතක තබා නොගනී) සහ ප්‍රති ro ලදායක බව දන්නා කරුණකි, මන්ද ඔවුන් අවශ්‍ය / අනවශ්‍ය උපුටා දැක්වීම් ව්‍යාකූල කරනු ඇත, ඒවායේ පිටපත් බිඳ දමා වැඩිදුර ඉගෙනීමට ඒවා පහත් කරයි.
පීටර්ස්

6
මගේ $ 0.02 වනුයේ සෑම දෙයක්ම උපුටා දැක්වීමට නිර්දේශ කිරීම හොඳ උපදෙසකි. අනවශ්‍ය දෙයක් වැරදියට උපුටා දැක්වීම හානිකර නොවන අතර, අවශ්‍ය දෙයක් උපුටා දැක්වීමට වැරදියට අපොහොසත් වීම හානිකර ය. එබැවින්, වචන බෙදීම සිදු වූ විට ඇති වන සංකීර්ණතා කිසි විටෙකත් තේරුම් නොගන්නා ෂෙල් ස්ක්‍රිප්ට් කතුවරුන්ගෙන් බහුතරයකට, සෑම දෙයක්ම උපුටා දැක්වීම අවශ්‍ය අවස්ථාවන්හිදී පමණක් උපුටා දැක්වීමට වඩා ආරක්ෂිත වේ.
godlygeek

6
Et පීටරිස් සහ දේවභක්තික: "උපුටා දැක්වීම් පිටපත බිඳ දැමිය හැකි සාධාරණ අවස්ථා තිබේද?" එය "සාධාරණ" යන්න පිළිබඳ ඔබේ අර්ථ දැක්වීම මත රඳා පවතී. ස්ක්‍රිප්ට් එකක් සකසන්නේ criteria="-type f"නම් find . $criteriaක්‍රියා කරයි, නමුත් find . "$criteria"ක්‍රියා නොකරයි.
ජී-මෑන් පවසන්නේ 'මොනිකා නැවත

22

මා දන්නා පරිදි, ද්විත්ව-උපුටා දැක්වීම් අවශ්‍ය වන්නේ අවස්ථා දෙකක් පමණක් වන අතර, එම අවස්ථා විශේෂ ෂෙල් පරාමිතීන් දෙක "$@"හා සම්බන්ධ වේ "$*"- ඒවා ද්විත්ව උපුටා දැක්වීම්වල ඇතුළත් කර ඇති විට වෙනස් ලෙස පුළුල් කිරීමට නියම කර ඇත. අනෙක් සෑම අවස්ථාවකම (සමහර විට, ෂෙල්-විශේෂිත අරාව ක්‍රියාත්මක කිරීම හැර) ප්‍රසාරණයක හැසිරීම වින්‍යාසගත කළ හැකි දෙයකි - ඒ සඳහා විකල්ප තිබේ.

ඇත්ත වශයෙන්ම, ද්විත්ව උපුටා දැක්වීම වළක්වා ගත යුතු යැයි මින් අදහස් නොකෙරේ - ඊට පටහැනිව, එය බොහෝ විට කවචය විසින් ලබා දිය යුතු ප්‍රසාරණයක් සීමා කිරීමේ වඩාත් පහසු සහ ශක්තිමත් ක්‍රමය විය හැකිය. එහෙත්, මම සිතන්නේ, විකල්පයන් දැනටමත් ප්‍රවීණව පැහැදිලි කර ඇති පරිදි, කවචය වටිනාකමක් පුළුල් කළ විට කුමක් සිදුවේද යන්න සාකච්ඡා කිරීමට මෙය කදිම ස්ථානයකි.

කවචය, එහි හදවතේ සහ ආත්මයේ (එවැනි අය සඳහා) විධාන පරිවර්ථකයෙකි - එය විශාල, අන්තර්ක්‍රියාකාරී වැනි විග්‍රහයකි sed. ඔබගේ ෂෙල් ප්රකාශය නම් හිර මත whitespace ඔබ ෂෙල් අර්ථකථනය ක්රියාවලිය සම්පූර්ණයෙන්ම අවබෝධ නැති නිසා හෝ ඒ හා සමාන නම් එය ඉතා ඉඩ ඇත - එය ලබන ක්රියාමාර්ග විධානය ආදාන ප්රකාශය පරිවර්තනය විශේෂයෙන් ආකාරය ඇයි. කවචයේ කාර්යය වන්නේ:

  1. ආදානය පිළිගන්න

  2. අර්ථ නිරූපණය හා බෙදී tokenized ආදාන බවට නිවැරදිව එය වචන

    • ආදාන වචන යනු $wordහෝ වැනි ෂෙල් සින්ටැක්ස් අයිතම වේecho $words 3 4* 5

    • වචන සැමවිටම වයිට්ස්පේස් මත බෙදී යයි - එය හුදෙක් වාක්‍ය ඛණ්ඩයකි - නමුත් එහි ආදාන ගොනුවේ කවචයට සේවය කළේ වචනාර්ථයෙන් සුදු පැහැති අක්ෂර පමණි.

  3. අවශ්‍ය නම් ඒවා විවිධ ක්ෂේත්‍රවලට පුළුල් කරන්න

    • ක්ෂේත්රවල ප්රති result ලය වන්නේ වචන විස්තාරණය කිරීමයි - ඒවා අවසන් ක්රියාත්මක කළ හැකි විධානය සාදයි

    • ආදාන වචනයක් සෑම විටම තනි ක්ෂේත්‍රයකට ඇගයීමට ලක් කළ යුතුය "$@", $IFS ක්ෂේත්‍ර බෙදීම් සහ මාර්ග නාම ප්‍රසාරණය හැර .

  4. ඉන්පසු ලැබෙන විධානය ක්‍රියාත්මක කිරීමට

    • බොහෝ අවස්ථාවන්හීදී මෙය අර්ථ නිරූපණය කිරීමේ ප්‍රති results ල යම් ආකාරයකින් හෝ වෙනත් ආකාරයකින් ලබා දීම ඇතුළත් වේ

මිනිසුන් බොහෝ විට පවසන්නේ කවචය මැලියම් එකක් වන අතර, මෙය සත්‍ය නම්, එය ඇලී ඇත්තේ තර්ක ලැයිස්තුවක් හෝ ක්ෂේත්‍රයක් - ඒවා එක් ක්‍රියාවලියකට හෝ වෙනත් ක්‍රියාවලියකට execය. බොහෝ ෂෙල් වෙඩි NULබයිට් හොඳින් හසුරුවන්නේ නැත - කිසිසේත් නම් - එයට හේතුව ඔවුන් දැනටමත් එය මත බෙදී ඇති බැවිනි. කවචයට exec බොහෝ දේ ඇති අතර එය කළ යුත්තේ එය නියමිත වේලාවට NULපද්ධති කර්නලයට භාර දෙන සීමිත පරාමිතීන් සමඟ ය exec. ඔබ කවචයේ පරිසීමකය එහි වෙන් කළ දත්ත සමඟ අන්තර් සම්බන්ධ කරන්නේ නම්, කවචය බොහෝ විට එය ඉස්කුරුප්පු කරනු ඇත. එහි අභ්‍යන්තර දත්ත ව්‍යුහයන් - බොහෝ වැඩසටහන් මෙන් - එම පරිසීමකය මත රඳා පවතී. zsh, විශේෂයෙන්, මෙය ඉස්කුරුප්පු නොකරයි.

හා ඒ කොහෙද තියෙන්නේ $IFSතුළ ය. $IFSක නිරතුරුවම - එසේ ම settable - shell එකෙන් ෂෙල් පුළුල් කිරීම් බෙදී කළ යුතු ආකාරය නිර්වචනය කරන බව ෂෙල් පරාමිතිය වචනය සඳහා ක්ෂේත්රයේ විශේෂයෙන් එම අගය දේ මත - ක්ෂේත්ර delimit යුතුය. $IFSභේදවලට හැර වෙනත් ක්රමයන්හි මත පුළුල් කිරීම් ශෙලය NULඅගය එම ගැලපෙන බව පුළුල් ප්රතිඵලයක් බයිට් හෝ, වෙනත් වචන වලින් ෂෙල් ආදේශක - $IFSසමග NULසිය අභ්යන්තර දත්ත-පෙලගැස්මක් දී. ඔබ එය දෙස බලන විට සෑම ක්ෂේත්‍ර බෙදීම් කවච ප්‍රසාරණයක්ම $IFSඅවලංගු කරන ලද දත්ත අරාවක් බව ඔබට පෙනෙනු ඇත.

බව ද තේරුම් ගැනීම වැදගත් වේ $IFSපමණක් යි ඇසීමට බව පුළුල් කිරීම් නැහැ ඔබ සමඟ කළ හැකි - දැනටමත් එසේ පිරිසගේ "ද්විත්ව උපුටා දක්වයි. ඔබ ප්‍රසාරණයක් උපුටා දක්වන විට ඔබ එය හිසට සහ අවම වශයෙන් එහි වටිනාකමේ වලිගයට වෙන් කරන්න. $IFSවෙන් කිරීමට ක්ෂේත්‍ර නොමැති බැවින් එවැනි අවස්ථාවන්හිදී අදාළ නොවේ. ඇත්ත වශයෙන්ම, ද්විත්ව උපුටා දැක්වීමේ ප්‍රසාරණයක් හිස් අගයකට සකසා ඇති විට, සමාන නොවන ක්ෂේත්‍ර බෙදීම් හැසිරීම, නොකියවූ ප්‍රසාරණයකට ප්‍රදර්ශනය කරයි IFS=.

උපුටා දක්වා නොමැති නම්, $IFSඑයම $IFSවෙන් කරන ලද ෂෙල් ප්‍රසාරණයකි. එය නිශ්චිත අගයකට පෙරනිමිය <space><tab><newline>- මේ තුනම තුළ ඇති විට විශේෂ ගුණාංග පෙන්වයි $IFS. සඳහා වෙනත් කිසිදු අගය ඇති ෙහයින් $IFSතනි කිරීමට ඇගයීමට විශේෂිතව දක්වා ක්ෂේත්රයේ පුළුල් අනුව සිදුවීමක් , $IFS whitespace - තුනක් එම ඕනෑම - පුළුල් අනුව තනි ක්ෂේත්රයට elide කිරීමට නියම කර අනුපිළිවෙල අනුක්රමය සම්පූර්ණයෙන්ම elided ඇත අවර සහ මෙරට ප්රමුඛ පෙළේ /. මෙය බොහෝ විට උදාහරණයකින් තේරුම් ගැනීමට පහසුය.

slashes=///// spaces='     '
IFS=/; printf '<%s>' $slashes$spaces
<><><><><><     >
IFS=' '; printf '<%s>' $slashes$spaces
</////>
IFS=; printf '<%s>' $slashes$spaces
</////     >
unset IFS; printf '<%s>' "$slashes$spaces"
</////     >

නමුත් එය හුදෙක් $IFS- ඉල්ලූ පරිදි වචන බෙදීම හෝ සුදු අවකාශය පමණි , එබැවින් විශේෂ චරිත ගැන කුමක් කිව හැකිද?

කවචය - පෙරනිමියෙන් - ලැයිස්තුගත නොවූ විට ඇතැම් නොකල ටෝකන ( ?*[මෙහි වෙනත් තැනක සඳහන් කර ඇති පරිදි) බහු ක්ෂේත්‍ර වෙත පුළුල් කරයි. මෙය පථ නාම විස්තාරණය හෝ ග්ලෝබින් ලෙස හැඳින්වේ . එය ඇදහිය නොහැකි තරම් ප්‍රයෝජනවත් මෙවලමක් වන අතර, එය කවචයේ විග්‍රහ අනුපිළිවෙලෙහි බෙදීමෙන් පසුව සිදුවන බැවින් එය $ IFS මගින් බලපෑමට ලක් නොවේ - මාර්ග නාම ප්‍රසාරණයකින් ජනනය වන ක්ෂේත්‍ර ගොනු නාමවල හිස / වලිගය මත වෙන් කරනු ලැබේද යන්න නොසලකා. ඒවායේ අන්තර්ගතයේ දැනට පවතින ඕනෑම අක්ෂර අඩංගු වේ $IFS. මෙම හැසිරීම පෙරනිමියෙන් සකසා ඇත - නමුත් එය වෙනත් ආකාරයකින් ඉතා පහසුවෙන් වින්‍යාස කර ඇත.

set -f

එමඟින් කවචයට උපදෙස් දෙන්නේ ග්ලෝබල් නොකරන ලෙසයි . වත්මන් කවචය වෙනත් නව කවච ක්‍රියාවලියකින් ප්‍රතිස්ථාපනය කළහොත් හෝ ....

set +f

... කවචයට නිකුත් කරනු ලැබේ. ද්වි-උපුටා දැක්වීම් - $IFS ක්ෂේත්‍ර බෙදීම් සඳහා ද ඔවුන් කරන පරිදි - මෙම ගෝලීය සැකසුම පුළුල් කිරීමකට අනවශ්‍ය කරයි. ඒ නිසා:

echo "*" *

... මාර්ග නාම ප්‍රසාරණය දැනට සක්‍රීය කර ඇත්නම්, තර්කයකට වඩා වෙනස් ප්‍රති results ල ලැබෙනු ඇත - පළමුවැන්න එහි වචනාර්ථමය වටිනාකමට පමණක් පුළුල් වන බැවින් (තනි තරු ලක්‍ෂණය, එනම්, කිසිසේත්ම නොවේ) සහ දෙවැන්න එකම දෙයකට පමණි වත්මන් වැඩ කරන නාමාවලියෙහි ගැලපෙන ගොනු නාම කිසිවක් නොමැති නම් (එය ඒ සියල්ලටම ගැලපේ) . කෙසේ වෙතත් ඔබ එසේ කරන්නේ නම්:

set -f; echo "*" *

... තර්ක දෙකෙහිම ප්‍රති results ල සමාන වේ - *එම අවස්ථාවේ දී එය පුළුල් නොවේ.


මම ඇත්ත වශයෙන්ම @ ස්ටෙෆාන් චැසෙලාස් සමඟ එකඟ වෙමි, එය (බොහෝ දුරට) උදව් කරනවාට වඩා දේවල් ව්‍යාකූල කරයි ... නමුත් මට එය පෞද්ගලිකව ප්‍රයෝජනවත් බව පෙනී ගියේය, එබැවින් මම ඉහළට ඔසවා තැබුවෙමි. IFSඇත්ත වශයෙන්ම ක්‍රියා කරන ආකාරය පිළිබඳ මට දැන් වඩා හොඳ අදහසක් (සහ උදාහරණ කිහිපයක්) තිබේ . මම නැහැ එය වනු ඇත ඇයි ලබා ගැනීමයි මෙතෙක් කට්ටලයක් කිරීම හොඳ අදහසක් විය IFSපෙරනිමි හැර වෙනත් දෙයක් කිරීමට.
වයිල්ඩ්කාඩ්

1
Ild විල්ඩ්කාඩ් - එය ක්ෂේත්‍ර පරිසීමකය. ඔබට විචල්‍යයක අගයක් තිබේ නම් එය ඔබට විවිධ ක්ෂේත්‍ර වෙත ව්‍යාප්ත කිරීමට අවශ්‍යය $IFS. cd /usr/bin; set -f; IFS=/; for path_component in $PWD; do echo $path_component; doneමුද්රණය කරයි \nනම් usr\nඑවිට bin\n. පළමුවැන්න echoහිස් ය, මන්ද /එය ශුන්‍ය ක්ෂේත්‍රයකි. Path_components හට නව රේඛා හෝ අවකාශ හෝ වෙනත් ඕනෑම දෙයක් තිබිය හැකිය - සංරචක බෙදී ඇති /නිසා මිස පෙරනිමි අගය නොවේ. මිනිසුන් එය awkකෙසේ හෝ වේවා. ඔබේ
කවචයද

3

ලිපිගොනු නාමවල අවකාශයන් සහ නාමාවලි නාමවල අවකාශයන් සහිත විශාල වීඩියෝ ව්‍යාපෘතියක් මා සතුව තිබුණි. අතර find -type f -print0 | xargs -0, බොහොමයක් අරමුණු සඳහා ක්රියා හා විවිධ ෂෙල් වෙඩි හරහා, මම අභිරුචි IFS (ආදාන ක්ෂේත්රය වෙන්කර) භාවිතා කරමින් බව සොයා ඔබ bash භාවිතා කරන්නේ නම් වඩා නම්යශීලී බවක් ලබා දෙයි. පහත දැක්වෙන ස්නිපටය bash භාවිතා කරන අතර IFS නව රේඛාවකට සකසයි; ඔබගේ ගොනු නාමවල නව රේඛා නොමැති නම්:

(IFS=$'\n'; for i in $(find -type f -print) ; do
    echo ">>>$i<<<"
done)

අයිඑෆ්එස් නැවත අර්ථ දැක්වීම හුදකලා කිරීම සඳහා පරෙන්ස් භාවිතා කිරීම සැලකිල්ලට ගන්න. IFS නැවත ලබා ගන්නේ කෙසේද යන්න ගැන මම වෙනත් ලිපි කියවා ඇත්තෙමි, නමුත් මෙය පහසුය.

තව දුරටත්, අයිඑෆ්එස් නව රේඛාවට සැකසීම මඟින් ඔබට පෙර ෂෙල් විචල්‍යයන් සැකසීමට සහ ඒවා පහසුවෙන් මුද්‍රණය කිරීමට ඉඩ ලබා දේ. උදාහරණයක් ලෙස, නව රේඛා බෙදුම්කරුවන් ලෙස භාවිතා කරමින් මට විචල්ය V වර්ධක ලෙස වර්ධනය කළ හැකිය:

V=""
V="./Ralphie's Camcorder/STREAM/00123.MTS,04:58,05:52,-vf yadif"
V="$V"$'\n'"./Ralphie's Camcorder/STREAM/00111.MTS,00:00,59:59,-vf yadif"
V="$V"$'\n'"next item goes here..."

සහ ඊට අනුරූපව:

(IFS=$'\n'; for v in $V ; do
    echo ">>>$v<<<"
done)

දැන් මට echo "$V"නව රේඛා ප්‍රතිදානය කිරීම සඳහා ද්විත්ව උපුටා දැක්වීම් භාවිතා කරමින් V හි සැකසුම "ලැයිස්තුගත" කළ හැකිය . ( පැහැදිලි කිරීම සඳහා මෙම නූලට බැර කරන්න $'\n'.)


3
නමුත් පසුව ඔබට නව රේඛා හෝ ග්ලෝබ් අක්ෂර අඩංගු ගොනු නාමයන් සමඟ ගැටලු ඇති වේ. මෙයද බලන්න: සොයාගැනීම්වල ප්‍රතිදානය නරක අතට හැරෙන්නේ ඇයි? . භාවිතා කරන්නේ නම් zsh, ඔබට භාවිතා කළ හැකිය IFS=$'\0'සහ භාවිතා කළ හැකිය -print0( zshපුළුල් කිරීම් මත ග්ලෝබල් කිරීම නොකරයි, එබැවින් ගෝලීය අක්ෂර එහි ගැටළුවක් නොවේ).
ස්ටෙෆාන් චසෙලාස්

1
මෙය අවකාශයන් සහිත ගොනු නාම සමඟ ක්‍රියා කරයි, නමුත් එය සතුරු විය හැකි ගොනු නාම හෝ අහම්බෙන් “විකාර” ගොනු නාමයන්ට එරෙහිව ක්‍රියා නොකරයි. ආදේශ කිරීමෙන් ඔබට ආදේශක කාඩ්පත් අක්ෂර අඩංගු ගොනු නාම ගැටළුව පහසුවෙන් විසඳා ගත හැකිය set -f. අනෙක් අතට, නව ප්‍රවේශයන් අඩංගු ගොනු නාම සමඟ ඔබේ ප්‍රවේශය මූලික වශයෙන් අසමත් වේ. ගොනු නාම හැර වෙනත් දත්ත සමඟ කටයුතු කරන විට, එය හිස් අයිතම සමඟ ද අසමත් වේ.
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

හරි, මගේ අවවාදය නම් එය ගොනු නාමවල නව රේඛා සමඟ ක්‍රියා නොකරනු ඇත. කෙසේ වෙතත්, මම විශ්වාස කරන්නේ අප පිස්සුවෙන් ලැජ්ජාවට
රස්

මට විශ්වාස නෑ ඇයි මේකට අඩු අගයක් ලැබුණේ කියලා. මෙය අවකාශයන් සහිත ගොනු නාමයන් හරහා නැවත සැකසීම සඳහා ඉතා සාධාරණ ක්‍රමයකි. -Pprint0 භාවිතා කිරීම සඳහා xargs අවශ්‍ය වන අතර එම දාමය භාවිතා කිරීමට අපහසු දේවල් තිබේ. මට කණගාටුයි කවුරුහරි මගේ පිළිතුරට එකඟ නොවුනත් එය අවතක්සේරු කිරීමට හේතුවක් නැත.
රුස්

0

භාවිතා කරන ක්රමය find directory -print0 | xargs -0සියලු විශේෂ හැසිරවිය යුතුය. කෙසේ වෙතත්, එයට එක් ගොනුවකට / නාමාවලියකට එක් PID අවශ්‍ය වේ, එය කාර්ය සාධන ගැටලුවකට සවි කළ හැකිය.

මා මෑතකදී හමු වූ ශක්තිමත් (සහ ක්‍රියාකාරී) ගොනු හැසිරවීමේ තවත් ක්‍රමයක් විස්තර කිරීමට මට ඉඩ දෙන්න , findප්‍රතිදානය ටැබ් වලින් වෙන් කරන ලද CSV දත්ත ලෙස පසු සැකසුම් කළ යුතු නම් එය සුදුසු වේ , උදා: AWK. එවැනි සැකසුම් වලදී, ඇත්ත වශයෙන්ම ගොනු නාමවල ඇති ටැබ් සහ නව රේඛා පමණක් කඩාකප්පල් වේ:

නාමාවලිය හරහා පරිලෝකනය කෙරේ find directory -printf '%P\t///\n'. මාර්ගයේ ටැබ් හෝ නව රේඛා අඩංගු නොවේ නම්, මෙය CSV ක්ෂේත්‍ර දෙකක් සහිත එක් වාර්තාවකට මග පාදයි: මාර්ගය සහ ක්ෂේත්‍රය අඩංගු වේ ///.

මාර්ගයේ ටැබ් එකක් තිබේ නම්, ක්ෂේත්‍ර තුනක් ඇත: මාර්ග කැබැල්ල 1, මාර්ග කැබැල්ල 2 සහ ක්ෂේත්‍රය ///.

නව රේඛාවක් අඩංගු නම්, වාර්තා දෙකක් ඇත: පළමු වාර්තාවේ මාර්ග කැබැල්ල 1 ද දෙවන වාර්තාවේ මාර්ග කොටස් 2 ද ක්ෂේත්‍රය ද අඩංගු වේ ///.

දැන් ප්‍රධාන කරුණ නම් ///ස්වාභාවිකවම මාර්ගවල සිදුවිය නොහැකි වීමයි. එසේම, එය එක්තරා ආකාරයක ජල ආරක්ෂිත ගැලවීමක් හෝ පර්යන්තයක් වේ.

findප්‍රතිදානය පරිලෝකනය කරන (AWK) වැඩසටහනක් ලිවීමට ද හැකි අතර, එය සොයා ගන්නා තෙක්/// , එය නව ක්ෂේත්‍රයක් ටැබ් එකක් බවත්, නව වාර්තාවක් මාර්ගයේ නව රේඛාවක් බවත් දැන දැනම එම කොටස් එකට දමයි.

පටිති ආරක්ෂිතව ලෙස පලා කළ හැකි ///tසහ හිස් පේලි ගැන ආරක්ෂිතව ලෙස පලා ගත හැකි ///n, නැවත බව දැන, විසින් ///ස්වභාවිකව ගොනුව මාර්ග සිදු කළ නොහැක. සැකසීමෙන් යම් ප්‍රතිදානයක් ජනනය වන විට, ටැබ් සහ නව රේඛා වෙත පරිවර්තනය කිරීම ///tසහ ///nනැවත සිදුවීම අවසානයේ සිදුවිය හැකිය.

ඔව්, එය සංකීර්ණ බවක් පෙනේ, නමුත් හෝඩුවාව වන්නේ PID දෙකක් පමණක් අවශ්‍ය බවය: findසහ awkවිස්තර කරන ලද ඇල්ගොරිතම ක්‍රියාත්මක කරන අවස්ථාව. එය වේගවත් ය.

අදහස මගේ නොවේ, ඩිරෙක්ටරි සමමුහුර්තකරණය සඳහා මෙම නව (2019) බෑෂ් පිටපතෙහි එය ක්‍රියාත්මක කර ඇති බව මට පෙනී ගියේය : Zaloha.sh . ඇත්ත වශයෙන්ම ඇල්ගොරිතම විස්තර කරන ලේඛනයක් ඔවුන් සතුව ඇත.

ගොනු නාමවල ඇති විශේෂ අක්ෂර මගින් එම වැඩසටහන බිඳ දැමීමට / යටපත් කිරීමට මට නොහැකි විය. එය නිව්ලයින් සහ ටැබ් පමණක් නම් කළ නාමාවලි නිවැරදිව සකසන ලදි ...


2
කෙසේ වෙතත්, ///මාර්ගවල “ස්වාභාවිකව” සිදු නොවන අතර පරෙස්සම් වන්න - නිදසුනක් ලෙස findඅඩංගු මාර්ග ගොඩනඟන්නේ නැත ///- එය පරිශීලක ආදානය ( find ///some////where) තුළ සිදුවිය හැකි අතර එය අතිරික්ත කප්පාදුවලින් සංයුක්ත මාර්ග වලින් පැන නගී. ඔබ යෙදවුම් සාමාන්‍යකරණය කරන තාක් කල් කමක් නැත, නමුත් යෙදවුම් සාමාන්‍යකරණය කිරීම අත්‍යවශ්‍ය නොවේ.
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

1
xargsනැහැ නැහැ ආදාන ගොනු එක් ක්රියාවලිය පවත්වාගෙන. ඊට පටහැනිව, එය විධාන රේඛාවේ හැකි තරම් ගොනු නාම ගොඩ ගසයි, බොහෝ විට එහි ප්‍රති input ලය වනුයේ ආදාන ප්‍රමාණය කුඩා නම් තනි PID ය. find . -maxdepth 1 -print0 | xargs -0 sh -c 'echo "$$ $@"' _සරල නිරූපණයක් සඳහා උත්සාහ කරන්න . xargs -n1එක් එක් ක්‍රියාවලිය වෙන වෙනම ක්‍රියාත්මක කිරීමට අවශ්‍ය වෙනත් විකල්ප සමඟ ඔබට එය බල කළ හැකිය . සමහර විට තර්කය xargsඅත්‍යවශ්‍ය නොවේ නම්, එක් තර්කයකට එක් ක්‍රියාවලියක් ක්‍රියාත්මක කිරීමෙන් වැළකී සිටීම දුෂ්කර ය.
ත්‍රිත්ව

-1

ඉහත සඳහන් කර ඇති සියලුම ආරක්‍ෂිත ඇඟවුම් සලකා බලා ඔබ විශ්වාස කරන සහ විචල්‍යයන් පාලනය කර ඇති බව උපකල්පනය කිරීමෙන් ඔබේ පුළුල් වන විට හිස් අවකාශයන් භාවිතා කරමින් බහු මාර්ග තිබිය හැකිය eval. එහෙත් ප්රවේසම් වන්න!

$ FILES='"a b" c'
$ eval ls $FILES
ls: a b: No such file or directory
ls: c: No such file or directory
$ FILES='a\ b c'
$ eval ls $FILES
ls: a b: No such file or directory
ls: c: No such file or directory
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.