আপনি কিভাবে ফাইলের প্রতিটি লাইনের জন্য একটি কমান্ড চালাবেন?


161

উদাহরণস্বরূপ, এই মুহুর্তে আমি কয়েকটি ফাইল পরিবর্তনের জন্য নিম্নলিখিতগুলি ব্যবহার করছি যার ইউনিক্স পথগুলি আমি একটি ফাইলে লিখেছি:

cat file.txt | while read in; do chmod 755 "$in"; done

আরও কি মার্জিত, নিরাপদ উপায় আছে?

উত্তর:


127

লাইন দ্বারা একটি ফাইল লাইন পড়ুন এবং আদেশগুলি কার্যকর করুন: 4 টি উত্তর

এটি কারণ যেখানে কেবল 1 টি উত্তর নেই ...

  1. shell কমান্ড লাইন সম্প্রসারণ
  2. xargs উত্সর্গীকৃত সরঞ্জাম
  3. while read কিছু মন্তব্য সহ
  4. while read -uইন্টারেক্টিভ প্রসেসিংয়ের fdজন্য ডেডিকেটেড ব্যবহার করে (নমুনা)

ওপি অনুরোধ সম্পর্কিত: ফাইলের তালিকাভুক্ত সমস্ত লক্ষ্যবস্তুতে চলছেchmod , xargsএটি নির্দেশিত সরঞ্জাম। তবে কিছু অন্যান্য অ্যাপ্লিকেশন, ফাইলের স্বল্প পরিমাণ ইত্যাদি,

  1. কমান্ড লাইন আর্গুমেন্ট হিসাবে পুরো ফাইলটি পড়ুন।

    যদি আপনার ফাইলটি খুব বড় না হয় এবং সমস্ত ফাইলের নাম ভাল হয় (ফাঁকা স্থান বা অন্যান্য বিশেষ অক্ষর ছাড়াই), আপনি shellকমান্ড লাইন সম্প্রসারণ ব্যবহার করতে পারেন । কেবল:

    chmod 755 $(<file.txt)

    অল্প পরিমাণে ফাইলের (লাইন) জন্য, এই আদেশটি হালকা।

  2. xargs সঠিক সরঞ্জাম

    বড় পরিমাণে ফাইল, বা আপনার ইনপুট ফাইলের লাইনগুলির প্রায় কোনও সংখ্যার জন্য ...

    অনেকের জন্য binutils সরঞ্জাম, মত chown, chmod, rm, cp -t...

    xargs chmod 755 <file.txt

    আপনার যদি বিশেষ অক্ষর এবং / অথবা প্রচুর লাইন থাকে file.txt

    xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)

    যদি আপনার কমান্ডটি প্রবেশের মাধ্যমে ঠিক 1 বার চালানো দরকার:

    xargs -0 -n 1 chmod 755 < <(tr \\n \\0 <file.txt)

    chmodযুক্তি হিসাবে একাধিক ফাইল গ্রহণ করার জন্য এটি এই নমুনার জন্য প্রয়োজন হয় না , তবে এটি প্রশ্নের শিরোনামের সাথে মেলে।

    কিছু বিশেষ ক্ষেত্রে, আপনি এমনকি উত্পন্ন কমান্ডগুলিতে ফাইল আর্গুমেন্টের অবস্থান নির্ধারণ করতে পারেন xargs:

    xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0 <file.txt)

    seq 1 5ইনপুট হিসাবে পরীক্ষা

    এটা চেষ্টা কর:

    xargs -n 1 -I{} echo Blah {} blabla {}.. < <(seq 1 5)
    Blah 1 blabla 1..
    Blah 2 blabla 2..
    Blah 3 blabla 3..
    Blah 4 blabla 4..
    Blah 5 blabla 5..

    যেখানে কমান্ড প্রতি লাইনে একবার করা হয়

  3. while read এবং রূপগুলি।

    ওপির পরামর্শ অনুসারে cat file.txt | while read in; do chmod 755 "$in"; doneকাজ করবে তবে 2 টি সমস্যা রয়েছে:

    • cat |একটি হল বেহুদা কাঁটাচামচ এবং

    • | while ... ;doneএকটি পরিণত হবে subshell যেখানে পরিবেশ পর disapear হবে ;done

    সুতরাং এটি আরও ভাল লেখা যেতে পারে:

    while read in; do chmod 755 "$in"; done < file.txt

    কিন্তু,

    • আপনি পতাকা $IFSএবং readপতাকা সম্পর্কে সতর্ক হতে পারে :

      help read
      read: read [-r] ... [-d delim] ... [name ...]
          ...
          Reads a single line from the standard input... The line is split
          into fields as with word splitting, and the first word is assigned
          to the first NAME, the second word to the second NAME, and so on...
          Only the characters found in $IFS are recognized as word delimiters.
          ...
          Options:
            ...
            -d delim   continue until the first character of DELIM is read, 
                       rather than newline
            ...
            -r do not allow backslashes to escape any characters
          ...
          Exit Status:
          The return code is zero, unless end-of-file is encountered...

      কিছু ক্ষেত্রে, আপনার ব্যবহারের প্রয়োজন হতে পারে

      while IFS= read -r in;do chmod 755 "$in";done <file.txt

      স্ট্র্যাঞ্জ ফাইল নামগুলির সাথে সমস্যা এড়ানোর জন্য। এবং যদি আপনি সমস্যাগুলি সমাধান করতে পারেন তবে UTF-8:

      while LANG=C IFS= read -r in ; do chmod 755 "$in";done <file.txt
    • আপনি STDINপড়ার জন্য ব্যবহার করার সময় file.txt, আপনার স্ক্রিপ্ট ইন্টারেক্টিভ হতে পারে না (আপনি STDINআর ব্যবহার করতে পারবেন না )।

  4. while read -u, নিবেদিত ব্যবহার করে fd

    সিনট্যাক্স: এ while read ...;done <file.txtপুনঃনির্দেশিত STDINহবে file.txt। এর অর্থ, তারা প্রক্রিয়া শেষ না করা অবধি প্রক্রিয়া মোকাবেলা করতে সক্ষম হবেন না।

    আপনি যদি ইন্টারেক্টিভ সরঞ্জাম তৈরি করার পরিকল্পনা করেন , আপনাকে STDINকিছু বিকল্প ফাইল বর্ণনাকারী ব্যবহার এড়াতে হবে এবং ব্যবহার করতে হবে

    ধ্রুবক ফাইল বর্ণনাকারী আছেন: 0জন্য stdin , 1জন্য stdout- এ এবং 2জন্য stderr । আপনি এগুলি দেখতে পেলেন:

    ls -l /dev/fd/

    অথবা

    ls -l /proc/self/fd/

    সেখান থেকে, আপনাকে ফাইল বর্ণনাকারী হিসাবে 0এবং এর মধ্যে 63(আরও বেশি করে, সত্যিকারের sysctlসরঞ্জামের উপর নির্ভর করে ) অব্যবহৃত সংখ্যা বাছাই করতে হবে :

    এই ডেমোটির জন্য, আমি এফডি ব্যবহার করব 7:

    exec 7<file.txt      # Without spaces between `7` and `<`!
    ls -l /dev/fd/

    তাহলে আপনি read -u 7এইভাবে ব্যবহার করতে পারেন :

    while read -u 7 filename;do
        ans=;while [ -z "$ans" ];do
            read -p "Process file '$filename' (y/n)? " -sn1 foo
            [ "$foo" ]&& [ -z "${foo/[yn]}" ]&& ans=$foo || echo '??'
        done
        if [ "$ans" = "y" ] ;then
            echo Yes
            echo "Processing '$filename'."
        else
            echo No
        fi
    done 7<file.txt

    done

    বন্ধ করতে fd/7:

    exec 7<&-            # This will close file descriptor 7.
    ls -l /dev/fd/

    নোটা: আমি স্ট্রাইকড সংস্করণটি ছেড়ে দিয়েছি কারণ সমান্তরাল প্রক্রিয়া সহ অনেকগুলি I / O করার সময় এই বাক্য গঠনটি কার্যকর হতে পারে:

    mkfifo sshfifo
    exec 7> >(ssh -t user@host sh >sshfifo)
    exec 6<sshfifo

3
হিসাবে xargsমত প্রয়োজন নেই, কিছু বৈশিষ্ট্য এই ধরনের উত্তর জন্য initialy বিল্ড ছিল বর্তমান পরিবেশে দীর্ঘ যতটা সম্ভব কমান্ড বিল্ডিং invoking জন্য chmod, যতটা সম্ভব কম যেমন এই ক্ষেত্রে হ্রাস কাটাচামচ efficience নিশ্চিত। while ;do..done <$fileইমপ্লাই 1 টি ফাইলের জন্য 1 টি কাঁটাচামচ চালাচ্ছেন। xargsহাজার ফাইলের জন্য 1 টি কাঁটাচামচ চালাতে পারে ... একটি নির্ভরযোগ্য পদ্ধতিতে।
এফ। হাউরি

1
তৃতীয় কমান্ড একটি মেকফিলে কাজ করে না কেন? আমি "অপ্রত্যাশিত টোকেনের কাছে সিনট্যাক্স ত্রুটি` <'"পেয়েছি, তবে কমান্ড লাইন থেকে সরাসরি চালানো কাজ করে।
উড্রো বারলো

2
এটি মেকফিলের নির্দিষ্ট সিনট্যাক্সের সাথে যুক্ত বলে মনে হচ্ছে। আপনি কমান্ড লাইনটি বিপরীত করার চেষ্টা করতে পারেন:cat file.txt | tr \\n \\0 | xargs -0 -n1 chmod 755
এফ। হাউরি

@ এফ.হৌরি কোনও কারণে tr \\n \\0 <file.txt |xargs -0 [command]আপনার বর্ণিত পদ্ধতির চেয়ে প্রায় 50% দ্রুত is
ফিল্ড 294

অক্টোবর 2019, নতুন সম্পাদনা, ইন্টারেক্টিভ ফাইল প্রসেসরের নমুনা যুক্ত করুন।
এফ.হৌরি

150

হ্যাঁ.

while read in; do chmod 755 "$in"; done < file.txt

এইভাবে আপনি কোনও catপ্রক্রিয়া এড়াতে পারবেন ।

catপ্রায়শই এই জাতীয় উদ্দেশ্যে খারাপ হয়। আপনি বিড়ালের ব্যবহারহীন ব্যবহার সম্পর্কে আরও পড়তে পারেন


চলুন এক cat একটি ভাল ধারণা আছে, কিন্তু এই ক্ষেত্রে, নির্দেশিত কমান্ডxargs
এফ Hauri

এই লিঙ্কটি প্রাসঙ্গিক বলে মনে হচ্ছে না, সম্ভবত ওয়েব পৃষ্ঠার সামগ্রী পরিবর্তন হয়েছে? বাকি উত্তরটি দুর্দান্ত যদিও :)
স্টারবিয়াম্রেনবোলাবস

পুনঃটুইট মনে হচ্ছে পৃষ্ঠাটি সরানো হয়েছে। আমি আবার সংযুক্ত হয়েছি এবং এখন ঠিক করা উচিত। ধন্যবাদ :)
পিপি

1
ধন্যবাদ! এটি সহায়ক ছিল, বিশেষত যখন আপনাকে কল করার চেয়ে অন্য কিছু করার প্রয়োজন হয় chmod(অর্থাত্ ফাইলের প্রতিটি লাইনের জন্য সত্যই একটি কমান্ড চালান)।
প্রতি লন্ডবার্গ

ব্যাকস্ল্যাশগুলির সাথে সাবধান! unix.stackexchange.com/a/7561/28160 থেকে - " read -rস্ট্যান্ডার্ড ইনপুট থেকে একটি লাইন পড়ে ( ব্যাকস্ল্যাশ ব্যাখ্যা readছাড়াই -r, আপনি এটি চান না)"।
ব্রাজিলিয়ান গায়

16

আপনার যদি একটি ভাল নির্বাচক থাকে (উদাহরণস্বরূপ, একটি ডায়ারের সমস্ত টেক্সট ফাইল) আপনি করতে পারেন:

for i in *.txt; do chmod 755 "$i"; done

লুপ জন্য বাশ

বা আপনার একটি বৈকল্পিক:

while read line; do chmod 755 "$line"; done <file.txt

কি কাজ করে না তা হ'ল লাইনে ফাঁকা স্থান থাকলে ইনপুটটি ফাঁক দিয়ে বিভক্ত হয়, লাইন দিয়ে নয়।
মাইকেল ফক্স

@ মিশেল ফক্স: স্পেস সহ লাইনগুলি বিভাজক পরিবর্তন করে সমর্থন করা যেতে পারে। এটিকে নতুন লাইনে পরিবর্তন করতে, স্ক্রিপ্ট / কমান্ডের আগে 'আইএফএস' পরিবেশ পরিবর্তনশীল সেট করুন।
উদাহরণস্বরূপ

আমার শেষ মন্তব্যে টাইপ করুন। হওয়া উচিত: আইএফএস = $ '\ n'
কোডস্নিফার

14

আপনি যদি জানেন যে ইনপুটটিতে আপনার কোনও সাদা জায়গা নেই:

xargs chmod 755 < file.txt

যদি পাথগুলিতে শ্বেত স্থান থাকতে পারে এবং আপনার জিএনইউ xargs থাকে:

tr '\n' '\0' < file.txt | xargs -0 chmod 755

আমি xargs সম্পর্কে জানি, তবে (দুঃখের সাথে) এটি ব্যাশ অন্তর্নির্মিত বৈশিষ্ট্যগুলি যেমন পড়া এবং পড়ার চেয়ে নির্ভরযোগ্য সমাধান হিসাবে কম বলে মনে হয়। এছাড়াও, আমার কাছে জিএনইউ xargs নেই তবে আমি ওএস এক্স ব্যবহার করছি এবং xargs এরও এখানে একটি -0 বিকল্প রয়েছে। উত্তর করার জন্য ধন্যবাদ.
বাজ

1
@ হক নং: xargsমজবুত। এই সরঞ্জামটি খুব পুরানো এবং তার কোডটি দৃ strongly ়ভাবে পুনর্বিবেচনা করা হয়েছে । শেল সীমাবদ্ধতার (k৪ কেচার / লাইন বা অন্য কিছু) লাইন তৈরির লক্ষ্যে তাঁর লক্ষ্য ছিল প্রাথমিক। এখন এই সরঞ্জামটি খুব বড় ফাইলগুলির সাথে কাজ করতে পারে এবং চূড়ান্ত কমান্ডে কাঁটাচামড়ার সংখ্যা হ্রাস করতে পারে। দেখুন আমার উত্তর এবং / অথবা man xargs
এফ হাউরি

@ হাওক কোন উপায়ে নির্ভরযোগ্য সমাধান কম? যদি এটি লিনাক্স, ম্যাক / বিএসডি এবং উইন্ডোজে কাজ করে (হ্যাঁ, এমএসওয়াইএসজিআইটি-এর বান্ডিলগুলি জিএনইউ xargs), তবে এটি যতটা নির্ভরযোগ্য।
ক্যামিলো মার্টিন

1
যারা এখনও অনুসন্ধান ফলাফল থেকে এটি সন্ধান করছেন তাদের জন্য ... আপনি হোমব্রিউ ( brew install findutils) ব্যবহার করে ম্যাকোজে জিএনইউ xargs ইনস্টল করতে পারেন এবং তারপরে জিএনইউ xargs আহ্বান করতে পারেন gxargs, যেমনgxargs chmod 755 < file.txt
জেস

13

আপনি যদি প্রতিটি লাইনের সমান্তরালে আপনার কমান্ডটি চালাতে চান তবে আপনি জিএনইউ সমান্তরাল ব্যবহার করতে পারেন

parallel -a <your file> <program>

আপনার ফাইলের প্রতিটি লাইন একটি আর্গুমেন্ট হিসাবে প্রোগ্রামে পাস করা হবে। ডিফল্টরূপে parallelআপনার সিপিইউ গণনা যতটা থ্রেড চালায়। তবে আপনি এটি দিয়ে নির্দিষ্ট করতে পারেন-j


3

আমি দেখতে পাচ্ছি যে আপনি বাশকে ট্যাগ করেছেন, তবে পার্ল এটি করারও একটি ভাল উপায় হবে:

perl -p -e '`chmod 755 $_`' file.txt

আপনি সঠিক ফাইলগুলি পেয়েছেন তা নিশ্চিত করার জন্য আপনি একটি রেজেক্সও প্রয়োগ করতে পারেন, উদাহরণস্বরূপ কেবলমাত্র টেক্সট ফাইলগুলি প্রক্রিয়া করার জন্য:

perl -p -e 'if(/\.txt$/) `chmod 755 $_`' file.txt

যা হচ্ছে তার "প্রাকদর্শন" করতে, কেবল ডাবল উদ্ধৃতি দিয়ে ব্যাকটিকগুলি প্রতিস্থাপন করুন এবং প্রিপেন্ড করুন print:

perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt

2
ব্যাকটিক্স কেন ব্যবহার করবেন? chmod
পারেলের

1
আপনি চাইবেন perl -lpe 'chmod 0755, $_' file.txt- -l"অটো-
চম্প

1

আপনি এডাব্লুকে ব্যবহার করতে পারেন যা আপনাকে ফাইলটি পরিচালনা করতে আরও স্বাচ্ছন্দ্য দিতে পারে

awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt

আপনার ফাইলের ক্ষেত্রে যদি ক্ষেত্র বিভাজক থাকে:

field1, field2, field3

আপনি প্রথম ক্ষেত্রটি পেতে

awk -F, '{ print "chmod 755 "$1"" | "/bin/sh"}' file.txt

আপনি জিএনইউ ডকুমেন্টেশন https://www.gnu.org/software/gawk/manual/html_node/Very-Simple.html#Very-Simple এ আরও বিশদ পরীক্ষা করতে পারেন


0

যুক্তি অন্যান্য অনেকগুলি উদ্দেশ্যে প্রযোজ্য। এবং / home / ফাইল সিস্টেম থেকে প্রতিটি ব্যবহারকারীর .sh_history কীভাবে পড়বেন? যদি তাদের হাজার হাজার হয়?

#!/bin/ksh
last |head -10|awk '{print $1}'|
 while IFS= read -r line
 do
su - "$line" -c 'tail .sh_history'
 done

এখানে স্ক্রিপ্টটি https://github.com/imvieira/SysAdmin_DevOps_Scriptts/blob/master/get_and_run.sh


0

আমি জানি এখনও দেরি হয়ে গেছে

যদি কোনও সুযোগের পরিবর্তে আপনি উইন্ডোজ সেভড টেক্সট ফাইলের \r\nপরিবর্তে চালিত \nহন তবে আউটপুটটি আপনি বিভ্রান্ত হয়ে পড়তে পারেন যদি আপনার কমান্ডটি পড়ার লাইনের পরে যুক্তিরূপে স্টাফ থাকে। সুতরাং \rউদাহরণস্বরূপ মুছে ফেলুন :

cat file | tr -d '\r' | xargs -L 1 -i echo do_sth_with_{}_as_line
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.