আমি কীভাবে বাশ লুপের তালিকায় সাদা স্থান থেকে বাঁচতে পারি?


121

আমার একটি বাশ শেল স্ক্রিপ্ট রয়েছে যা একটি নির্দিষ্ট ডিরেক্টরিতে সমস্ত শিশু ডিরেক্টরিতে (তবে ফাইল নয়) লুপ করে। সমস্যাটি হ'ল কিছু ডিরেক্টরি নামের শূন্যস্থান রয়েছে।

এখানে আমার পরীক্ষা ডিরেক্টরিটির বিষয়বস্তু রয়েছে:

$ls -F test
Baltimore/  Cherry Hill/  Edison/  New York City/  Philadelphia/  cities.txt

এবং কোডগুলি যে ডিরেক্টরিগুলির মাধ্যমে লুপ করে:

for f in `find test/* -type d`; do
  echo $f
done

এখানে ফলাফল:

পরীক্ষা / বাল্টিমোর
পরীক্ষা / চেরি
পাহাড়
পরীক্ষা / এডিসনের 
পরীক্ষা / নিউ
ইয়র্ক
শহর
পরীক্ষা / ফিলাডেলফিয়া

চেরি হিল এবং নিউ ইয়র্ক সিটি 2 বা 3 পৃথক এন্ট্রি হিসাবে বিবেচিত হয়।

আমি ফাইলের নামগুলি উদ্ধৃত করার চেষ্টা করেছি, এরকম:

for f in `find test/* -type d | sed -e 's/^/\"/' | sed -e 's/$/\"/'`; do
  echo $f
done

কিন্তু কোন উপকার.

এটি করার একটি সহজ উপায় আছে।


নীচের উত্তরগুলি দুর্দান্ত। তবে এটিকে আরও জটিল করে তোলার জন্য - আমি সর্বদা আমার পরীক্ষার ডিরেক্টরিতে তালিকাবদ্ধ ডিরেক্টরিগুলি ব্যবহার করতে চাই না। কখনও কখনও আমি পরিবর্তে কমান্ড-লাইন প্যারামিটার হিসাবে ডিরেক্টরিতে পাস করতে চাই।

আমি চার্লসের আইএফএস স্থাপনের পরামর্শ নিয়েছি এবং নিম্নলিখিতগুলি নিয়ে এসেছি:

dirlist="${@}"
(
  [[ -z "$dirlist" ]] && dirlist=`find test -mindepth 1 -type d` && IFS=$'\n'
  for d in $dirlist; do
    echo $d
  done
)

কমান্ড লাইন আর্গুমেন্টে ফাঁকা স্থান না পাওয়া পর্যন্ত এটি ঠিক কাজ করে (এমনকি সেই সমস্ত যুক্তি উদ্ধৃত হয়)। উদাহরণস্বরূপ, স্ক্রিপ্টটিকে এভাবে কল করা: test.sh "Cherry Hill" "New York City"নিম্নলিখিত আউটপুট উত্পাদন করে:

চেরি
পাহাড়
নতুন
ইয়র্ক
শহর

পুনরায়: সম্পাদনা করুন, list="$@"সম্পূর্ণ মানটির তালিকার নেসটি সম্পূর্ণরূপে বাদ দেয়, এটি একটি স্ট্রিংয়ে ধসে যায়। আমার উত্তরে অনুগ্রহ করে ঠিক যেমনটি দেওয়া হয়েছে ঠিক তেমন অনুসরণ করুন - এরকম কোনও নিয়োগের কোথাও কোথাও তাকে উত্সাহ দেওয়া হয় না; আপনি যদি কোনও প্রোগ্রামে কমান্ড-লাইন আর্গুমেন্টের একটি তালিকা পাস করতে চান তবে আপনার সেগুলি একটি অ্যারেতে সংগ্রহ করা উচিত এবং সেই অ্যারেটি সরাসরি প্রসারিত করা উচিত।
চার্লস ডাফি

উত্তর:


105

প্রথমত, এটি সেভাবে করবেন না। find -execসঠিকভাবে ব্যবহার করা সবচেয়ে ভাল উপায় :

# this is safe
find test -type d -exec echo '{}' +

অন্যান্য নিরাপদ পদ্ধতির নাম হল NUL- সমাপ্ত তালিকা ব্যবহার করা, যদিও এটির জন্য আপনার সন্ধানের সমর্থন প্রয়োজন -print0:

# this is safe
while IFS= read -r -d '' n; do
  printf '%q\n' "$n"
done < <(find test -mindepth 1 -type d -print0)

আপনি অনুসন্ধান থেকে একটি অ্যারেও তৈরি করতে পারেন এবং পরে সেই অ্যারেটি পাস করতে পারেন:

# this is safe
declare -a myarray
while IFS= read -r -d '' n; do
  myarray+=( "$n" )
done < <(find test -mindepth 1 -type d -print0)
printf '%q\n' "${myarray[@]}" # printf is an example; use it however you want

যদি আপনার -print0সন্ধানটি সমর্থন করে না , তবে আপনার ফলাফলটি অনিরাপদ - নীচে যদি ফাইলগুলির নামে নতুন লাইনের উপস্থিতি উপস্থিত থাকে (যা হ্যাঁ, আইনী) তবে এটি পছন্দ মতো আচরণ করবে না:

# this is unsafe
while IFS= read -r n; do
  printf '%q\n' "$n"
done < <(find test -mindepth 1 -type d)

যদি উপরের কোনওটি ব্যবহার না করে, একটি তৃতীয় পদ্ধতি (শব্দ এবং বিভাজন করার আগে সাবপ্রসেসের পুরো আউটপুটটি পড়ায় উভয় সময় এবং মেমরির ব্যবহারের ক্ষেত্রে কম দক্ষ) একটি IFSভেরিয়েবল ব্যবহার করতে হয় যা না করে স্থান অক্ষর ধারণ করে না। Globbing বন্ধ করুন ( set -fযেমন উল্লিখিত glob অক্ষর ধারণকারী স্ট্রিং প্রতিরোধ) [], *বা ?থেকে প্রসারিত হচ্ছে:

# this is unsafe (but less unsafe than it would be without the following precautions)
(
 IFS=$'\n' # split only on newlines
 set -f    # disable globbing
 for n in $(find test -mindepth 1 -type d); do
   printf '%q\n' "$n"
 done
)

অবশেষে, কমান্ড-লাইন প্যারামিটার ক্ষেত্রে, আপনার শেল যদি তাদের সমর্থন করে তবে আপনাকে অ্যারে ব্যবহার করা উচিত (যেমন এটি কেএসএস, ব্যাশ বা জেডএস):

# this is safe
for d in "$@"; do
  printf '%s\n' "$d"
done

বিচ্ছেদ বজায় রাখা হবে। উল্লেখ্য যে উদ্ধৃতি (এবং এর $@পরিবর্তে ব্যবহার $*) গুরুত্বপূর্ণ। অ্যারেগুলি অন্যান্য উপায়েও পপুলেট করা যায় যেমন গ্লোব এক্সপ্রেশন:

# this is safe
entries=( test/* )
for d in "${entries[@]}"; do
  printf '%s\n' "$d"
done

1
এক্সেকের জন্য '+' গন্ধ সম্পর্কে জানতেন না know মিষ্টি
জোহানেস স্কাউব - lit

1
দেখে মনে হচ্ছে এটি যেমন জার্গার্সের মতো প্রদত্ত কমান্ডের শেষে কেবল যুক্তিগুলি রাখতে পারে: / যা আমাকে মাঝে মাঝে
বগড করে দেয়

আমার মনে হয়-এক্সেক [নাম] {} + একটি জিএনইউ এবং 4.4-বিএসডি এক্সটেনশন। (কমপক্ষে, এটি সোলারিস 8 এ প্রকাশিত হয়নি, এবং আমার মনে হয় না এটি এআইএক্স ৪.৩-এও ছিল।) আমি অনুমান করি আমাদের বাকী
অংশগুলি জার্গসে পাইপিংয়ের

2
আমি এর আগে synt '\ n' সিনট্যাক্সটি আগে কখনও দেখিনি। ওটা কিভাবে কাজ করে? (আমি ভেবেছিলাম যে আইএফএস = '\ n' বা আইএফএস = "\ n" কাজ করবে, তবে কিছুই করবে না))
এমসিএস

1
@ ক্রোস্টালক এটি অবশ্যই সোলারিস 10 এ রয়েছে, আমি কেবল এটি ব্যবহার করেছি।
নিক

26
find . -type d | while read file; do echo $file; done

যাইহোক, ফাইল-নামটিতে নতুন লাইন থাকলে তা কাজ করে না। উপরেরটি হ'ল আমি জানি যখন আপনি আসলে কোনও ভেরিয়েবলের ডিরেক্টরি নাম রাখতে চান of আপনি যদি কিছু কমান্ড চালাতে চান তবে xargs ব্যবহার করুন।

find . -type d -print0 | xargs -0 echo 'The directory is: '

এক্সার্গসের দরকার নেই, সন্ধানী-এক্সেক দেখুন ... {} +
চার্লস ডাফি

4
@ চার্লস: প্রচুর সংখ্যক ফাইলের জন্য, জারগস আরও কার্যকর: এটি কেবল একটি প্রক্রিয়া তৈরি করে। -Exec বিকল্পটি প্রতিটি ফাইলের জন্য একটি নতুন প্রক্রিয়া কাঁটাচামচ করে, যা ধীরে ধীরে প্রস্থের ক্রম হতে পারে।
অ্যাডাম রোজেনফিল্ড

1
আমি আরও xargs পছন্দ। এই দুটি মূলত উভয়ই একই কাজ করবে বলে মনে হচ্ছে, যখন xargs এর আরও বিকল্প রয়েছে যেমন সমান্তরালভাবে চালানো
জোহানেস স্কাউব - লিটব

2
অ্যাডাম, এমন কোনও নয় যে '+' একজন যথাসম্ভব ফাইলের নাম সংগ্রহ করবে এবং তারপরে কার্যকর হবে utes তবে এটি সমান্তরালভাবে চলার মতো ঝরঝরে কাজ করবে না :)
জোহানেস স্কাউব -

2
দ্রষ্টব্য যে আপনি যদি ফাইলের নামগুলি দিয়ে কিছু করতে চান তবে আপনাকে সেগুলি উদ্ধৃত করতে হবে। উদাহরণস্বরূপ:find . -type d | while read file; do ls "$file"; done
ডেভিড মোলস

23

এখানে একটি সহজ সমাধান যা ফাইলনামে ট্যাব এবং / অথবা সাদা জায়গাগুলি পরিচালনা করে। আপনি যদি নতুন লাইনের মতো ফাইলের নামটিতে অন্য অদ্ভুত অক্ষরগুলি নিয়ে কাজ করতে চান তবে অন্য একটি উত্তর চয়ন করুন।

পরীক্ষা ডিরেক্টরি

ls -F test
Baltimore/  Cherry Hill/  Edison/  New York City/  Philadelphia/  cities.txt

ডিরেক্টরিগুলিতে যাওয়ার কোড

find test -type d | while read f ; do
  echo "$f"
done

"$f"যদি আর্গুমেন্ট হিসাবে ব্যবহৃত হয় তবে ফাইলের নাম অবশ্যই উদ্ধৃত করা উচিত ( )। উদ্ধৃতি ব্যতীত স্পেসগুলি আর্গুমেন্ট বিভাজক হিসাবে কাজ করে এবং একাধিক তর্কগুলি আমন্ত্রিত কমান্ডকে দেওয়া হয়।

এবং আউটপুট:

test/Baltimore
test/Cherry Hill
test/Edison
test/New York City
test/Philadelphia

ধন্যবাদ, এটি বর্তমানের ফোল্ডারে প্রতিটি ডিরেক্টরি কতটা স্থান ব্যবহার করছে তা তালিকা তৈরি করার জন্য আমি যে উপনামটি তৈরি করছিলাম তার জন্য এটি কাজ করেছিল, এটি পূর্ববর্তী অবতারের ফাঁকা জায়গাগুলির সাথে কিছু ডিয়ারকে দম বন্ধ করে দিচ্ছিল। এটি zsh এ কাজ করে, তবে অন্যান্য উত্তরগুলির মধ্যে কিছু দেয় নি:alias duc='ls -d * | while read D; do du -sh "$D"; done;'
টেড নালিড

2
আপনি যদি zsh ব্যবহার করছেন তবে আপনি এটিও করতে পারেন:alias duc='du -sh *(/)'
cbliard

@ cbliard এটি এখনও বগি। এটি একটি ফাইলের নাম দিয়ে, বলুন, একটি ট্যাব ক্রম বা একাধিক স্পেস দিয়ে চালানোর চেষ্টা করুন; আপনি নোট করবেন যে এটি কোনও একক জায়গায় স্থান পরিবর্তন করে, কারণ আপনি আপনার প্রতিধ্বনিতে উদ্ধৃতি দিচ্ছেন না। এবং তারপরে নতুন লাইনের সমন্বিত ফাইলের নাম রয়েছে ...
চার্লস ডাফি

@ চার্লসডুফি আমি ট্যাব সিকোয়েন্স এবং একাধিক স্পেস দিয়ে চেষ্টা করেছি। এটি উদ্ধৃতি সহ কাজ করে। আমি নিউলাইনগুলি নিয়েও চেষ্টা করেছি এবং এটি মোটেই কার্যকর হয় না। আমি সেই অনুযায়ী উত্তর আপডেট করেছি। এটি নির্দেশ করার জন্য আপনাকে ধন্যবাদ।
cbliard

1
@ cbliard রাইট - আপনার প্রতিধ্বনি কমান্ডে উদ্ধৃতি যুক্ত করা যা আমি পেয়ে যাচ্ছিলাম। নতুন লাইনের হিসাবে, আপনি সন্ধান -print0এবং ব্যবহার করে সেই কাজটি করতে পারেন IFS='' read -r -d '' f
চার্লস ডাফি

7

এটি স্ট্যান্ডার্ড ইউনিক্সের ক্ষেত্রে অত্যন্ত জটিল, এবং বেশিরভাগ সমাধান নিউলাইনগুলি বা অন্য কোনও চরিত্রের কুফল। তবে, আপনি যদি জিএনইউ সরঞ্জাম সেট ব্যবহার করে থাকেন তবে আপনি findবিকল্পটি কাজে লাগাতে -print0এবং xargsসম্পর্কিত বিকল্পটি -0(বিয়োগ-শূন্য) ব্যবহার করতে পারেন । দুটি অক্ষর রয়েছে যা একটি সরল ফাইলনেমে উপস্থিত হতে পারে না; এগুলি হ'ল স্ল্যাশ এবং NUL '\ 0'। স্পষ্টতই, স্ল্যাশ পথের নামগুলিতে উপস্থিত হয়, সুতরাং নামের শেষে চিহ্নিত করার জন্য একটি NUL '\ 0' ব্যবহারের জিএনইউ সমাধানটি উদ্ভাবক এবং বোকা-প্রমাণ।


4

শুধু রাখা হয় না কেন

IFS='\n'

কমান্ডের সামনে? এটি ফিল্ড বিভাজককে <স্পেস> <ট্যাব> <নিউ লাইন> থেকে কেবল <নিউলাইন> এ পরিবর্তন করে


4
find . -print0|while read -d $'\0' file; do echo "$file"; done

1
-d $'\0'অবিকল একই হিসাবে -d ''- কারণ ব্যাশ NUL-সমাপ্ত স্ট্রিং ব্যবহার করে, একটি খালি স্ট্রিং প্রথম অক্ষরটি একটি NUL হয়, এবং একই কারণে, NULs এ সব সি স্ট্রিং এর ভিতর প্রতিনিধিত্ব করা যাবে না।
চার্লস ডাফি

4

আমি ব্যবহার করি

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for f in $( find "$1" -type d ! -path "$1" )
do
  echo $f
done
IFS=$SAVEIFS

তা কি যথেষ্ট হবে না?
আইডিয়া http://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html থেকে নেওয়া হয়েছে


দুর্দান্ত টিপ: এটি একটি কমান্ড-লাইন ওসাস্ক্রিপ্ট (ওএস এক্স অ্যাপলস্ক্রিপ্ট) এর বিকল্পগুলির জন্য খুব সহায়ক, যেখানে স্পেসগুলি যুক্তিটিকে একাধিক পরামিতিগুলিতে বিভক্ত করে যেখানে কেবল একটির উদ্দেশ্য
টিম

না, এটি যথেষ্ট নয়। এটি অদক্ষ (এর অপ্রয়োজনীয় ব্যবহারের কারণে $(echo ...)), গ্লোব এক্সপ্রেশন সহ ফাইলের নামগুলি সঠিকভাবে পরিচালনা করে না, ফাইল নামগুলিতে হ্যান্ডেল করে না যা $'\b'or '\ n' অক্ষরগুলি সঠিকভাবে ধারণ করে , এবং তদুপরি হোয়াইটস্পেসের একাধিক রানকে একক হোয়াইটস্পেস অক্ষরে রূপান্তরিত করে the ভুল উদ্ধৃতি কারণে আউটপুট পার্শ্ব।
চার্লস ডাফি

4

স্ট্রিং হিসাবে তালিকাগুলি সংরক্ষণ করবেন না; এই সমস্ত বিস্ময়কর বিভ্রান্তি এড়াতে তাদের অ্যারে হিসাবে সংরক্ষণ করুন। এখানে একটি উদাহরণ স্ক্রিপ্ট যা পরীক্ষার সমস্ত উপ-ডিরেক্টরিতে কাজ করবে বা তার কমান্ড লাইনে সরবরাহিত তালিকা:

#!/bin/bash
if [ $# -eq 0 ]; then
        # if no args supplies, build a list of subdirs of test/
        dirlist=() # start with empty list
        for f in test/*; do # for each item in test/ ...
                if [ -d "$f" ]; then # if it's a subdir...
                        dirlist=("${dirlist[@]}" "$f") # add it to the list
                fi
        done
else
        # if args were supplied, copy the list of args into dirlist
        dirlist=("$@")
fi
# now loop through dirlist, operating on each one
for dir in "${dirlist[@]}"; do
        printf "Directory: %s\n" "$dir"
done

এখন এটি একটি বক্ররেখা বা দুটি নিক্ষিপ্ত করে একটি ডিরেক্টরি ডিরেক্টরিতে চেষ্টা করে দেখুন:

$ ls -F test
Baltimore/
Cherry Hill/
Edison/
New York City/
Philadelphia/
this is a dirname with quotes, lfs, escapes: "\''?'?\e\n\d/
this is a file, not a directory
$ ./test.sh 
Directory: test/Baltimore
Directory: test/Cherry Hill
Directory: test/Edison
Directory: test/New York City
Directory: test/Philadelphia
Directory: test/this is a dirname with quotes, lfs, escapes: "\''
'
\e\n\d
$ ./test.sh "Cherry Hill" "New York City"
Directory: Cherry Hill
Directory: New York City

1
এটির দিকে ফিরে তাকানো - পসিক্স শ এর সাথে একটি সমাধান আসলে ছিল : আপনি "$@"অ্যারেটিকে পুনরায় ব্যবহার করতে পারেন, এটিতে যুক্ত হয়ে set -- "$@" "$f"
চার্লস ডাফি

4

আপনি সাময়িকভাবে আইএফএস ব্যবহার করতে পারেন (অভ্যন্তরীণ ক্ষেত্র বিভাজক):

OLD_IFS=$IFS     # Stores Default IFS
IFS=$'\n'        # Set it to line break
for f in `find test/* -type d`; do
    echo $f
done

$IFS=$OLD_IFS


ব্যাখ্যা প্রদান করুন।
স্টিভ কে

আইএফএস পৃথককারী প্রতীক কী তা সুনির্দিষ্ট করে, তারপরে সাদা স্থানের সাথে ফাইলের নাম কেটে যাবে না।
10:36

$ আইএফএস = $ ওলডি_আইএফএস শেষে হওয়া উচিত: আইএফএস = $ ওলডি_আইএফএস
মিশেল

3

পিএস যদি এটি কেবল ইনপুটটিতে স্থান সম্পর্কে হয় তবে কিছু ডাবল উদ্ধৃতিগুলি আমার পক্ষে সুচারুভাবে কাজ করেছিল ...

read artist;

find "/mnt/2tb_USB_hard_disc/p_music/$artist" -type f -name *.mp3 -exec mpg123 '{}' \;

2

কি যোগ করতে জনাথন বলেন, ব্যবহার -print0জন্য বিকল্প findসাথে xargsনিম্নরূপ:

find test/* -type d -print0 | xargs -0 command

commandএটি সঠিক যুক্তি দিয়ে কমান্ডটি কার্যকর করবে ; এগুলির ফাঁকা জায়গাগুলি সহ ডিরেক্টরিগুলি সঠিকভাবে উদ্ধৃত করা হবে (অর্থাত তারা একটি যুক্তি হিসাবে পাস হবে)।


1
#!/bin/bash

dirtys=()

for folder in *
do    
 if [ -d "$folder" ]; then    
    dirtys=("${dirtys[@]}" "$folder")    
 fi    
done    

for dir in "${dirtys[@]}"    
do    
   for file in "$dir"/\*.mov   # <== *.mov
   do    
       #dir_e=`echo "$dir" | sed 's/[[:space:]]/\\\ /g'`   -- This line will replace each space into '\ '   
       out=`echo "$file" | sed 's/\(.*\)\/\(.*\)/\2/'`     # These two line code can be written in one line using multiple sed commands.    
       out=`echo "$out" | sed 's/[[:space:]]/_/g'`    
       #echo "ffmpeg -i $out_e -sameq -vcodec msmpeg4v2 -acodec pcm_u8 $dir_e/${out/%mov/avi}"    
       `ffmpeg -i "$file" -sameq -vcodec msmpeg4v2 -acodec pcm_u8 "$dir"/${out/%mov/avi}`    
   done    
done

উপরের কোডটি .mov ফাইলগুলিকে .avi তে রূপান্তর করবে। .Mov ফাইলগুলি বিভিন্ন ফোল্ডারে থাকে এবং ফোল্ডারের নামগুলিতেও সাদা স্পেস থাকে । আমার উপরের স্ক্রিপ্টটি একই ফোল্ডারে .mov ফাইলগুলিকে .avi ফাইলে রূপান্তর করবে। আমি জানি না এটি আপনার লোকদের সহায়তা করে কিনা।

কেস:

[sony@localhost shell_tutorial]$ ls
Chapter 01 - Introduction  Chapter 02 - Your First Shell Script
[sony@localhost shell_tutorial]$ cd Chapter\ 01\ -\ Introduction/
[sony@localhost Chapter 01 - Introduction]$ ls
0101 - About this Course.mov   0102 - Course Structure.mov
[sony@localhost Chapter 01 - Introduction]$ ./above_script
 ... successfully executed.
[sony@localhost Chapter 01 - Introduction]$ ls
0101_-_About_this_Course.avi  0102_-_Course_Structure.avi
0101 - About this Course.mov  0102 - Course Structure.mov
[sony@localhost Chapter 01 - Introduction]$ CHEERS!

চিয়ার্স!


echo "$name" | ...যদি nameহয় তবে এটি কাজ করে না -nএবং এটি কীভাবে ব্যাকস্ল্যাশ-এস্কেপ সিকোয়েন্সগুলির সাথে নামের সাথে আচরণ করে তা আপনার বাস্তবায়নের উপর নির্ভর করে - পসিক্স echoসে ক্ষেত্রে আচরণটি সুস্পষ্টভাবে সংজ্ঞায়িত করে তোলে (অন্যদিকে এক্সএসআই-এক্সটেন্ডেড পসিআইএক্স ব্যাকস্ল্যাশ-এস্কেপ সিকোয়েন্সগুলি স্ট্যান্ডার্ড-সংজ্ঞায়িত আচরণ করে , এবং জিএনইউ সিস্টেমগুলি - ব্যাশ সহ - POSIXLY_CORRECT=1প্রয়োগ না করে পসিক্স স্ট্যান্ডার্ডটি ভঙ্গ না করে -e(যেখানে অনুমানটি আউটপুট echo -eপ্রিন্ট -eকরা প্রয়োজন ) printf '%s\n' "$name" | ...নিরাপদ
চার্লস ডাফি 5'15

1

পথের নামগুলিতেও সাদা জায়গাগুলি নিয়ে কাজ করতে হয়েছিল। আমি শেষ পর্যন্ত যা করেছি তা ছিল একটি পুনরাবৃত্তি এবং for item in /path/*:

function recursedir {
    local item
    for item in "${1%/}"/*
    do
        if [ -d "$item" ]
        then
            recursedir "$item"
        else
            command
        fi
    done
}

1
functionকীওয়ার্ডটি ব্যবহার করবেন না - এটি আপনার কোডটিকে পসিক্স শ এর সাথে বেমানান করে তোলে তবে এর অন্য কোনও কার্যকর উদ্দেশ্য নেই। recursedir() {দুটি প্যারেন্স যুক্ত করে ফাংশন কীওয়ার্ডটি মুছে ফেলার সাথে আপনি কেবল একটি ফাংশন সংজ্ঞায়িত করতে পারেন এবং এটি সমস্ত পসিক্স-সম্মতিযুক্ত শাঁসের সাথে সামঞ্জস্যপূর্ণ হবে।
চার্লস ডাফি

1

ফাইল তালিকাটি একটি বাশ অ্যারেতে রূপান্তর করুন। এটি কোনও ব্যাশ ফাংশন থেকে অ্যারে ফিরিয়ে আনার জন্য ম্যাট ম্যাকক্লুরের পদ্ধতির ব্যবহার করে: http://notes-matthewlmcclure.blogspot.com/2009/12/return-array-from-bash-function-v-2.html ফলাফলটি একটি উপায় যে কোনও মাল্টি-লাইন ইনপুটকে বাশ অ্যারেতে রূপান্তর করতে।

#!/bin/bash

# This is the command where we want to convert the output to an array.
# Output is: fileSize fileNameIncludingPath
multiLineCommand="find . -mindepth 1 -printf '%s %p\\n'"

# This eval converts the multi-line output of multiLineCommand to a
# Bash array. To convert stdin, remove: < <(eval "$multiLineCommand" )
eval "declare -a myArray=`( arr=(); while read -r line; do arr[${#arr[@]}]="$line"; done; declare -p arr | sed -e 's/^declare -a arr=//' ) < <(eval "$multiLineCommand" )`"

for f in "${myArray[@]}"
do
   echo "Element: $f"
done

এই চরিত্রটি খারাপ চরিত্রগুলি উপস্থিত থাকা সত্ত্বেও কাজ করে প্রদর্শিত হয় এবং কোনও ইনপুটকে বাশ অ্যারেতে রূপান্তর করার একটি সাধারণ উপায়। অসুবিধাটি হ'ল যদি ইনপুট দীর্ঘ হয় তবে আপনি বাশের কমান্ড লাইন আকারের সীমা অতিক্রম করতে পারেন, বা প্রচুর পরিমাণে মেমরি ব্যবহার করতে পারেন।

অবশেষে তালিকায় কাজ করা লুপগুলি তালিকাটি পাইপযুক্ত রয়েছে এমন অসুবিধাও রয়েছে যে স্টিডিন পড়া সহজ নয় (যেমন ইনপুটটির জন্য ব্যবহারকারীকে জিজ্ঞাসা করা) এবং লুপটি একটি নতুন প্রক্রিয়া যাতে আপনি ভেবে দেখতে পারেন কেন পরিবর্তনশীল কেন আপনি লুপের ভিতরে সেট করেছেন লুপ শেষ হওয়ার পরে পাওয়া যায় না।

আমি আইএফএস সেট করাও অপছন্দ করি, এটি অন্য কোডগুলিতে গোলযোগ করতে পারে।


আপনি যদি IFS='' readএকই লাইনে ব্যবহার করেন তবে আইএফএস সেটিংটি কেবল পঠিত কমান্ডের জন্য উপস্থিত থাকে এবং এটি এড়ায় না। এইভাবে আইএফএস সেট করা অপছন্দ করার কোনও কারণ নেই।
চার্লস ডাফি

1

ভাল, আমি অনেক জটিল উত্তর দেখতে পাচ্ছি। আমি ইউটিলিটি সন্ধানের আউটপুটটি পাস করতে বা একটি লুপ লিখতে চাই না, কারণ ফাইন্ডের জন্য "এক্সিকিউটিভ" বিকল্প রয়েছে।

আমার সমস্যাটি হ'ল আমি dbf এক্সটেনশান সহ সমস্ত ফাইলকে বর্তমান ফোল্ডারে সরাতে চেয়েছিলাম এবং এর মধ্যে কয়েকটিতে সাদা স্থান রয়েছে।

আমি এটি এতটা মোকাবেলা করেছি:

 find . -name \*.dbf -print0 -exec mv '{}'  . ';'

আমার কাছে অনেক সহজ দেখাচ্ছে


0

আমার প্রশ্ন এবং আপনার মধ্যে কিছু সাদৃশ্য রয়েছে তা সন্ধান পেয়েছি । আপনি যদি কমান্ডগুলিতে যুক্তিগুলি পাস করতে চান তবে পরিশ্রম করুন

test.sh "Cherry Hill" "New York City"

যাতে তাদের প্রিন্ট আউট

for SOME_ARG in "$@"
do
    echo "$SOME_ARG";
done;

লক্ষ্য করুন $ @ দ্বিগুণ উদ্ধৃতি দ্বারা ঘিরে রয়েছে, এখানে কিছু নোট


0

নির্দিষ্ট ফোল্ডার থেকে ক্রমান্বয়ে বেশ কয়েকটি ডিরেক্টরি বা ফাইল সঙ্কুচিত করতে আমার একই ধারণাটি প্রয়োজন। Ls থেকে তালিকাটি পার্সেল করতে এবং নামের ফাঁকা জায়গার সমস্যা এড়াতে আমি awk ব্যবহার করে সমাধান করেছি।

source="/xxx/xxx"
dest="/yyy/yyy"

n_max=`ls . | wc -l`

echo "Loop over items..."
i=1
while [ $i -le $n_max ];do
item=`ls . | awk 'NR=='$i'' `
echo "File selected for compression: $item"
tar -cvzf $dest/"$item".tar.gz "$item"
i=$(( i + 1 ))
done
echo "Done!!!"

আপনি কি মনে করেন?


আমি মনে করি ফাইলগুলির মধ্যে নতুন লাইন থাকলে এটি সঠিকভাবে কাজ করবে না। সম্ভবত আপনি এটি চেষ্টা করা উচিত।
ব্যবহারকারী000001


-3

আমার জন্য এটি কাজ করে এবং এটি বেশ "পরিষ্কার":

for f in "$(find ./test -type d)" ; do
  echo "$f"
done

4
তবে এটি আরও খারাপ। সন্ধানের চারপাশে ডাবল-কোটগুলির ফলে সমস্ত পাথের নাম একক স্ট্রিং হিসাবে সংমিশ্রিত হয়। সমস্যাটি দেখতে ইকো একটি এলএসে পরিবর্তন করুন ।
এনভিআরএম

-4

সবেমাত্র একটি সাধারণ বৈকল্পিক সমস্যা ছিল ... টাইপ করা .flv ফাইলগুলিকে। এমপি 3 (ইয়ান) এ রূপান্তর করুন।

for file in read `find . *.flv`; do ffmpeg -i ${file} -acodec copy ${file}.mp3;done

অবিচ্ছিন্নভাবে সমস্ত ম্যাকিনটোস ব্যবহারকারীর ফ্ল্যাশ ফাইলগুলি সন্ধান করুন এবং সেগুলি অডিওতে রূপান্তর করুন (অনুলিপি করুন, কোনও ট্রান্সকোড নেই) ... এটি উপরের মত, কেবল 'ফাইল ইন ফাইলের' পরিবর্তে পড়ার বিষয়টি উল্লেখ করে পালিয়ে যাবে।


2
readপরে inতালিকা তোমাদের উপর iterating করছি আরো এক শব্দ। আপনি যা পোস্ট করেছেন তা হ'ল প্রশ্নকারীটির যা কিছু কাজ করে না তার একটি সামান্য ভাঙা সংস্করণ। আপনি হয়ত আলাদা কিছু পোস্ট করার ইচ্ছা পোষণ করেছেন, তবে এটি সম্ভবত অন্য উত্তরগুলির দ্বারা কভার করা যেতে পারে।
গিলস 'অশুভ হওয়া বন্ধ করুন'
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.