'Ls> ls.out' কেন 'ls.out' কে নামের তালিকায় অন্তর্ভুক্ত করবে?


26

$ ls > ls.outবর্তমান ডিরেক্টরিতে ফাইলের তালিকায় 'ls.out' অন্তর্ভুক্ত করার কারণ কেন ? কেন এটি হতে বেছে নেওয়া হয়েছিল? অন্যথায় না কেন?


3
সম্ভবত কারণ এটি প্রথমে একটি ফাইল তৈরি করে ls.out এবং তারপরে এটিতে আউটপুট লিখবে
দিমিত্রি পোডবার্সকি

1
আপনি যদি অন্তর্ভুক্তি এড়াতে চান তবে আপনি সর্বদা আলাদা ডিরেক্টরিতে আউটপুট ফাইল সঞ্চয় করতে পারেন। উদাহরণস্বরূপ, আপনি পিতামাতার ডিরেক্টরিটি বেছে নিতে পারেন (আপনি যদি ফাইল সিস্টেমের মূলে না থাকেন তবে) ls > ../ls.out
এল্ডার গীক

উত্তর:


36

কমান্ডটি মূল্যায়ন করার সময় >পুনর্নির্দেশটি প্রথমে সমাধান করা হয়: সুতরাং সময় lsসঞ্চালনের ফলে আউটপুট ফাইলটি ইতিমধ্যে তৈরি হয়ে গেছে।

>একই কমান্ডের মধ্যে পুনর্নির্দেশ ব্যবহার করে একই ফাইলটিতে পড়া এবং লেখার কারণে ফাইলটি কেটে যায়; কমান্ডটি চালুর সময় ইতিমধ্যে ফাইল কেটে ফেলা হয়েছে:

$ echo foo >bar
$ cat bar
foo
$ <bar cat >bar
$ cat bar
$ 

এটি এড়ানোর কৌশলগুলি:

  • <<<"$(ls)" > ls.out (পুনর্নির্দেশটি সমাধানের আগে চালানো দরকার এমন কোনও কমান্ডের জন্য কাজ করে)

    বাইরের কমান্ড মূল্যায়নের আগে কমান্ড প্রতিস্থাপন চালানো হয়, সুতরাং তৈরি lsহওয়ার আগে চালানো ls.outহয়:

    $ ls
    bar  foo
    $ <<<"$(ls)" > ls.out
    $ cat ls.out 
    bar
    foo
    
  • ls | sponge ls.out (পুনর্নির্দেশটি সমাধানের আগে চালানো দরকার এমন কোনও কমান্ডের জন্য কাজ করে)

    spongeফাইল শুধুমাত্র যখন নল নির্বাহ সমাপ্ত হয়েছে বাকি, তাই লিখেছেন lsসামনে চালানো হয় ls.outনির্মিত হয় ( spongeসাথে উপলব্ধ করা হয় moreutilsপ্যাকেজ):

    $ ls
    bar  foo
    $ ls | sponge ls.out
    $ cat ls.out 
    bar
    foo
    
  • ls * > ls.out( ls > ls.outএর নির্দিষ্ট ক্ষেত্রে কাজ করে)

    পুনঃনির্দেশটি সমাধান হওয়ার আগে ফাইলের নাম সম্প্রসারণ করা হয়, সুতরাং lsএর যুক্তিগুলিতে চালিত হবে, যা এতে থাকবে না ls.out:

    $ ls
    bar  foo
    $ ls * > ls.out
    $ cat ls.out 
    bar
    foo
    $
    

প্রোগ্রাম / স্ক্রিপ্ট / যা কিছু চলমান কেন আগে পুনর্নির্দেশগুলি সমাধান করা হয় সে সম্পর্কে, কেন এটি বাধ্যতামূলক করার জন্য আমি একটি নির্দিষ্ট কারণ দেখতে পাচ্ছি না তবে কেন এটি করা ভাল তার দুটি কারণ আমি দেখছি :

  • এসটিডিনকে আগেই পুনর্নির্দেশ না করা প্রোগ্রাম / স্ক্রিপ্ট / এসটিডিআইএন পুনর্নির্দেশ না হওয়া পর্যন্ত যা কিছু হোল্ড করে দেবে;

  • STDOUT পূর্বে পুনঃনির্দেশ না করা অবশ্যই অগত্যা শেল বাফারটিকে প্রোগ্রামের / স্ক্রিপ্টের / যা কিছু আউটপুট STDOUT পুনর্নির্দেশ না করা পর্যন্ত করা উচিত;

সুতরাং প্রথম ক্ষেত্রে সময় অপচয় এবং দ্বিতীয় ক্ষেত্রে সময় এবং স্মৃতি অপচয় করা।

আমার ক্ষেত্রে যা ঘটে তা হ'ল, আমি দাবি করছি না এগুলিই আসল কারণ; তবে আমি অনুমান করি যে সর্বোপরি যদি কারও একটি পছন্দ থাকে তবে তারা উপরে বর্ণিত কারণে যে কোনও উপায়ে পুনঃনির্দেশের সাথে চলে যাবে।


1
নোট করুন যে পুনঃনির্দেশের সময় শেলটি আসলে ডেটা স্পর্শ করে না (উভয়ই ইনপুট পুনঃনির্দেশ বা আউটপুট পুনঃনির্দেশ)। এটি কেবল ফাইলটি খোলে এবং ফাইল বিবরণকারীটিকে প্রোগ্রামে পাস করে।
পিটার গ্রিন

11

থেকে man bash:

ফেরৎ

কমান্ড কার্যকর করার আগে, শেল দ্বারা ব্যাখ্যা করা একটি বিশেষ স্বরলিপি ব্যবহার করে এর ইনপুট এবং আউটপুট পুনর্নির্দেশ করা যেতে পারে। পুনঃনির্দেশ কমান্ডের ফাইল হ্যান্ডলগুলি নকল করা, খুলতে, বন্ধ করতে, বিভিন্ন ফাইলকে উল্লেখ করার জন্য তৈরি করার অনুমতি দেয় এবং কমান্ডটি পড়ে এবং এতে লিখিত ফাইলগুলি পরিবর্তন করতে পারে।

প্রথম বাক্য, নির্দেশ দেয় যে আউটপুটটি stdinকমান্ড কার্যকর হওয়ার আগে ডায়রেক্টর ছাড়া অন্য কোথাও যেতে হবে । সুতরাং, ফাইলটিতে পুনঃনির্দেশিত করতে, ফাইলটি প্রথমে শেল নিজেই তৈরি করতে হবে।

কোনও ফাইল থাকা এড়াতে, আমি আপনাকে প্রথমে নামযুক্ত পাইপে আউটপুট পুনর্নির্দেশ করার পরামর্শ দিই, এবং তারপরে ফাইল করতে চাই। &ব্যবহারকারীর কাছে টার্মিনালের উপর নিয়ন্ত্রণ ফিরিয়ে দেওয়ার ব্যবহারটি লক্ষ্য করুন

DIR:/xieerqi
skolodya@ubuntu:$ mkfifo /tmp/namedPipe.fifo                                                                         

DIR:/xieerqi
skolodya@ubuntu:$ ls > /tmp/namedPipe.fifo &
[1] 14167

DIR:/xieerqi
skolodya@ubuntu:$ cat /tmp/namedPipe.fifo > ls.out

কিন্তু কেন?

এই সম্পর্কে চিন্তা করুন - আউটপুট কোথায় হবে? একটি প্রোগ্রাম মতো কাজগুলির হয়েছে printf, sprintf, puts, যা সব ডিফল্ট যান দ্বারা stdout, কিন্তু যদি ফাইল প্রথম স্থানে বিদ্যমান নয় তাদের আউটপুট ফাইল চলে যেতে পারে? এটি জলের মতো। প্রথমে কলটির নীচে গ্লাস না রেখে আপনি কি এক গ্লাস জল পেতে পারেন?


10

আমি বর্তমানের উত্তরগুলির সাথে একমত নই। কমান্ডটি চালুর আগে আউটপুট ফাইলটি খুলতে হবে বা কমান্ডের আউটপুট লিখতে হবে না।

এই কারণ আমাদের বিশ্বে "সবকিছুই একটি ফাইল" । স্ক্রিনে আউটপুট হল SDOUT (ওরফে ফাইল ডেস্ক্রিপ্টর 1)। টার্মিনালে লেখার জন্য অ্যাপ্লিকেশনটির জন্য, এটি fd1 খুলবে এবং এটিকে একটি ফাইলের মতো লিখবে।

আপনি যখন কোনও শেলের মধ্যে একটি অ্যাপ্লিকেশনের আউটপুট পুনর্নির্দেশ করবেন, আপনি fd1 পরিবর্তন করছেন যাতে এটি আসলে ফাইলটির দিকে নির্দেশ করে। আপনি যখন পাইপ দিবেন তখন আপনি একটি অ্যাপ্লিকেশনটির STDOUT পরিবর্তন করে অন্যের STDIN (fd0) হয়ে যান।


তবে এটি বলার অপেক্ষা রাখে না তবে এটি কীভাবে কাজ করে তা আপনি সহজেই দেখতে পারবেন strace। এটি বেশ ভারী জিনিস তবে উদাহরণটি খুব ছোট।

strace sh -c "ls > ls.out" 2> strace.out

এর মধ্যে strace.outআমরা নীচের হাইলাইটগুলি দেখতে পাই:

open("ls.out", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3

এটি ls.outহিসাবে খোলে fd3। শুধু লিখুন। সংক্ষিপ্ত আকারে (ওভাররাইট) উপস্থিত থাকলে অন্যথায় তৈরি করে।

fcntl(1, F_DUPFD, 10)                   = 10
close(1)                                = 0
fcntl(10, F_SETFD, FD_CLOEXEC)          = 0
dup2(3, 1)                              = 1
close(3)                                = 0

এটি কিছুটা জাগল। আমরা STDOUT (fd1) কে fd10 এড়িয়ে বন্ধ করে দিয়েছি। এটি হ'ল কারণ আমরা এই কমান্ডটি সহ সত্যিকারের STDOUT এ কিছুই আউটপুট দিচ্ছি না। এটি লিখিত হ্যান্ডেলটির অনুলিপি করে ls.outএবং আসলটি বন্ধ করে শেষ করে।

stat("/opt/wine-staging/bin/ls", 0x7ffc6bf028c0) = -1 ENOENT (No such file or directory)
stat("/home/oli/bin/ls", 0x7ffc6bf028c0) = -1 ENOENT (No such file or directory)
stat("/usr/local/sbin/ls", 0x7ffc6bf028c0) = -1 ENOENT (No such file or directory)
stat("/usr/local/bin/ls", 0x7ffc6bf028c0) = -1 ENOENT (No such file or directory)
stat("/usr/sbin/ls", 0x7ffc6bf028c0)    = -1 ENOENT (No such file or directory)
stat("/usr/bin/ls", 0x7ffc6bf028c0)     = -1 ENOENT (No such file or directory)
stat("/sbin/ls", 0x7ffc6bf028c0)        = -1 ENOENT (No such file or directory)
stat("/bin/ls", {st_mode=S_IFREG|0755, st_size=110080, ...}) = 0

এটি এক্সিকিউটেবলের জন্য অনুসন্ধান করছে। সম্ভবত দীর্ঘ পথ না পাওয়ার একটি পাঠ;)

clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f0961324a10) = 31933
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 31933
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=31933, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 31933
dup2(10, 1)                             = 1
close(10)                               = 0

তারপরে কমান্ডটি চলে এবং পিতামাতারা অপেক্ষা করেন। এই অপারেশন চলাকালীন কোনো stdout- এ আসলে খোলা ফাইল হ্যান্ডেল ম্যাপ হবে ls.out। যখন শিশু ইস্যু করে SIGCHLD, এটি পিতামাতার প্রক্রিয়াটি শেষ হয়ে যায় এবং এটি আবার শুরু করতে পারে tells এটি আরও কিছুটা জাগল এবং কাছাকাছি দিয়ে শেষ হয় ls.out

কেন নেই তাই অনেক আকাশ গান? না আমিও পুরোপুরি নিশ্চিত নই।


অবশ্যই আপনি এই আচরণটি পরিবর্তন করতে পারেন। আপনি স্মৃতিতে বাফার করতে পারেন এর মতো কিছু spongeএবং প্রসেসিং কমান্ড থেকে এটি অদৃশ্য হয়ে যাবে। আমরা এখনও ফাইল বর্ণনাকারীগুলিকে প্রভাবিত করছি তবে কোনও ফাইল-সিস্টেম-দৃশ্যমান উপায়ে নয়।

ls | sponge ls.out

6

শেলের পুনর্নির্দেশকরণ এবং পাইপ অপারেটরগুলির বাস্তবায়ন সম্পর্কে একটি দুর্দান্ত নিবন্ধও রয়েছে । যা দেখায় যে পুনর্নির্দেশটি কীভাবে বাস্তবায়ন করা যেতে পারে তাই দেখতে $ ls > ls.outপারে:

main(){
    close(1); // Release fd no - 1
    open("ls.out", "w"); // Open a file with fd no = 1
    // Child process
    if (fork() == 0) {
        exec("ls"); 
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.