$ ls > ls.out
বর্তমান ডিরেক্টরিতে ফাইলের তালিকায় 'ls.out' অন্তর্ভুক্ত করার কারণ কেন ? কেন এটি হতে বেছে নেওয়া হয়েছিল? অন্যথায় না কেন?
ls > ../ls.out
$ ls > ls.out
বর্তমান ডিরেক্টরিতে ফাইলের তালিকায় 'ls.out' অন্তর্ভুক্ত করার কারণ কেন ? কেন এটি হতে বেছে নেওয়া হয়েছিল? অন্যথায় না কেন?
ls > ../ls.out
উত্তর:
কমান্ডটি মূল্যায়ন করার সময় >
পুনর্নির্দেশটি প্রথমে সমাধান করা হয়: সুতরাং সময় 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 পুনর্নির্দেশ না করা পর্যন্ত করা উচিত;
সুতরাং প্রথম ক্ষেত্রে সময় অপচয় এবং দ্বিতীয় ক্ষেত্রে সময় এবং স্মৃতি অপচয় করা।
আমার ক্ষেত্রে যা ঘটে তা হ'ল, আমি দাবি করছি না এগুলিই আসল কারণ; তবে আমি অনুমান করি যে সর্বোপরি যদি কারও একটি পছন্দ থাকে তবে তারা উপরে বর্ণিত কারণে যে কোনও উপায়ে পুনঃনির্দেশের সাথে চলে যাবে।
থেকে 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
, কিন্তু যদি ফাইল প্রথম স্থানে বিদ্যমান নয় তাদের আউটপুট ফাইল চলে যেতে পারে? এটি জলের মতো। প্রথমে কলটির নীচে গ্লাস না রেখে আপনি কি এক গ্লাস জল পেতে পারেন?
আমি বর্তমানের উত্তরগুলির সাথে একমত নই। কমান্ডটি চালুর আগে আউটপুট ফাইলটি খুলতে হবে বা কমান্ডের আউটপুট লিখতে হবে না।
এই কারণ আমাদের বিশ্বে "সবকিছুই একটি ফাইল" । স্ক্রিনে আউটপুট হল 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
শেলের পুনর্নির্দেশকরণ এবং পাইপ অপারেটরগুলির বাস্তবায়ন সম্পর্কে একটি দুর্দান্ত নিবন্ধও রয়েছে । যা দেখায় যে পুনর্নির্দেশটি কীভাবে বাস্তবায়ন করা যেতে পারে তাই দেখতে $ 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");
}
}