আমি আশা করব
find . -delete
বর্তমান ডিরেক্টরি মুছতে, তবে তা হয় না। কেন না?
find . -print
।
cd ..; rm -r dir
বেশ স্পষ্ট শব্দার্থক দিয়ে অন্য শেলটি দিয়ে করতে পারেন ...
আমি আশা করব
find . -delete
বর্তমান ডিরেক্টরি মুছতে, তবে তা হয় না। কেন না?
find . -print
।
cd ..; rm -r dir
বেশ স্পষ্ট শব্দার্থক দিয়ে অন্য শেলটি দিয়ে করতে পারেন ...
উত্তর:
findutils
এটি সম্পর্কে সচেতন সদস্যরা , এটি * বিএসডি এর সাথে সামঞ্জস্যপূর্ণ:
"মুছে ফেলা" বাদ দেওয়ার অন্যতম কারণ " এটি * BSD এর সাথে সামঞ্জস্যের জন্য, যেখানে এই ক্রিয়টির উত্স।
সংবাদ findutils সোর্স কোড শো যে তারা আচরণ রাখা করার সিদ্ধান্ত নিয়েছে:
#20802: If -delete fails, find's exit status will now be non-zero. However, find still skips trying to delete ".".
[হালনাগাদ]
যেহেতু এই প্রশ্নটি অন্যতম আলোচ্য বিষয় হয়ে উঠেছে, তাই আমি ফ্রিবিএসডি উত্স কোডটিতে ঝাঁপিয়ে পড়েছি এবং আরও একটি দৃinc় বিশ্বাসযোগ্য কারণ সামনে আসছি।
আসুন ফ্রিবিএসডি-র ইউটিলিটি উত্স কোডটি দেখুন :
int
f_delete(PLAN *plan __unused, FTSENT *entry)
{
/* ignore these from fts */
if (strcmp(entry->fts_accpath, ".") == 0 ||
strcmp(entry->fts_accpath, "..") == 0)
return 1;
...
/* rmdir directories, unlink everything else */
if (S_ISDIR(entry->fts_statp->st_mode)) {
if (rmdir(entry->fts_accpath) < 0 && errno != ENOTEMPTY)
warn("-delete: rmdir(%s)", entry->fts_path);
} else {
if (unlink(entry->fts_accpath) < 0)
warn("-delete: unlink(%s)", entry->fts_path);
}
...
আপনি দেখতে পাচ্ছেন, এটি যদি বিন্দু এবং বিন্দু rmdir()
বিন্দুকে ছাঁটাই করে না, তবে এটি পসিক্স দ্বারা নির্ধারিত সি ফাংশনে পৌঁছে যাবে unistd.h
।
একটি সাধারণ পরীক্ষা করুন, বিন্দু / বিন্দু-বিন্দু যুক্তি সহ rmdir ফিরে আসবে -1:
printf("%d\n", rmdir(".."));
আসুন একনজরে দেখে নেওয়া যাক পসিআইএক্স কীভাবে rmdir বর্ণনা করে :
পথের যুক্তি যদি এমন কোনও পথকে বোঝায় যার চূড়ান্ত উপাদানটি হয় বিন্দু বা বিন্দু-বিন্দু, rmdir () ব্যর্থ হবে shall
কোনও কারণ কেন দেওয়া হয়নি shall fail
।
আমি rename
কিছু রিসো এন ব্যাখ্যা করলাম :
চক্রীয় ফাইল সিস্টেমের পাথগুলি রোধ করতে ডট বা ডট-ডট নামকরণ নিষিদ্ধ।
চক্রীয় ফাইল সিস্টেমের পথ ?
আমি সি প্রোগ্রামিং ল্যাঙ্গুয়েজ (দ্বিতীয় সংস্করণ) সন্ধান করি এবং ডিরেক্টরি বিষয় অনুসন্ধান করি, আশ্চর্যরূপে আমি খুঁজে পেলাম যে কোডটি অনুরূপ :
if(strcmp(dp->name,".") == 0 || strcmp(dp->name,"..") == 0)
continue;
আর মন্তব্য!
প্রতিটি ডিরেক্টরিতে সর্বদা নিজের জন্য "।" নামে অভিহিত থাকে এবং এর পিতামাতাকে ".."; এগুলি এড়িয়ে যেতে হবে, বা প্রোগ্রামটি চিরতরে লুপ হয়ে যাবে ।
"চিরকালের জন্য লুপ" , rename
এটি উপরেরটিকে "চক্রীয় ফাইল সিস্টেমের পাথ" হিসাবে বর্ণনা করার মতোই ।
আমি কোডটি সামান্য সংশোধন করেছি এবং এটি এই উত্তরের ভিত্তিতে কালী লিনাক্সে চালিত করতে :
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
void fsize(char *);
void dirwalk(char *, void (*fcn)(char *));
int
main(int argc, char **argv) {
if (argc == 1)
fsize(".");
else
while (--argc > 0) {
printf("start\n");
fsize(*++argv);
}
return 0;
}
void fsize(char *name) {
struct stat stbuf;
if (stat(name, &stbuf) == -1 ) {
fprintf(stderr, "fsize: can't access %s\n", name);
return;
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
dirwalk(name, fsize);
printf("%81d %s\n", stbuf.st_size, name);
}
#define MAX_PATH 1024
void dirwalk(char *dir, void (*fcn)(char *))
{
char name[MAX_PATH];
struct dirent *dp;
DIR *dfd;
if ((dfd = opendir(dir)) == NULL) {
fprintf(stderr, "dirwalk: can't open %s\n", dir);
return;
}
while ((dp = readdir(dfd)) != NULL) {
sleep(1);
printf("d_name: S%sG\n", dp->d_name);
if (strcmp(dp->d_name, ".") == 0
|| strcmp(dp->d_name, "..") == 0) {
printf("hole dot\n");
continue;
}
if (strlen(dir)+strlen(dp->d_name)+2 > sizeof(name)) {
printf("mocha\n");
fprintf(stderr, "dirwalk: name %s/%s too long\n",
dir, dp->d_name);
}
else {
printf("ice\n");
(*fcn)(dp->d_name);
}
}
closedir(dfd);
}
দেখা যাক:
xb@dnxb:/test/dot$ ls -la
total 8
drwxr-xr-x 2 xiaobai xiaobai 4096 Nov 20 04:14 .
drwxr-xr-x 3 xiaobai xiaobai 4096 Nov 20 04:14 ..
xb@dnxb:/test/dot$
xb@dnxb:/test/dot$ cc /tmp/kr/fsize.c -o /tmp/kr/a.out
xb@dnxb:/test/dot$ /tmp/kr/a.out .
start
d_name: S..G
hole dot
d_name: S.G
hole dot
4096 .
xb@dnxb:/test/dot$
এটি সঠিকভাবে কাজ করে, এখন যদি আমি continue
নির্দেশটির বাইরে মন্তব্য করি :
xb@dnxb:/test/dot$ cc /tmp/kr/fsize.c -o /tmp/kr/a.out
xb@dnxb:/test/dot$ /tmp/kr/a.out .
start
d_name: S..G
hole dot
ice
d_name: S..G
hole dot
ice
d_name: S..G
hole dot
ice
^C
xb@dnxb:/test/dot$
আপনি দেখতে পাচ্ছেন যে, আমাকে এই অসীম লুপ প্রোগ্রামটি মারতে Ctrl+ ব্যবহার Cকরতে হবে।
'..' ডিরেক্টরিটি তার প্রথম এন্ট্রি '..' পড়ে এবং চিরকালের জন্য লুপ করে।
উপসংহার:
জিএনইউ * বিএসডি-তে ইউটিলিটির findutils
সাথে সামঞ্জস্য করার চেষ্টা করুন ।find
find
* বিএসডি-তে ইউটিলিটি অভ্যন্তরীণভাবে rmdir
পসিএক্স-কমপ্লায়েন্ট সি ফাংশন ব্যবহার করে যা বিন্দু / বিন্দু বিন্দু অনুমোদিত নয়।
rmdir
ডট / ডট-ডটকে অনুমতি না দেওয়ার কারণ হ'ল চক্রীয় ফাইল সিস্টেমের পথগুলি প্রতিরোধ করা।
কে অ্যান্ড আর রচিত সি প্রোগ্রামিং ল্যাঙ্গুয়েজে ডট / ডট-ডট কীভাবে চিরকালের লুপ প্রোগ্রামে নিয়ে যাবে তার উদাহরণ দেখায়।
কারণ আপনার find
আদেশটি .
ফলাফল হিসাবে ফিরে আসে returns এর তথ্য পৃষ্ঠা থেকে rm
:
যার সর্বশেষ ফাইলের নাম উপাদানটি এমন কোনও ফাইল সরানোর কোনও প্রচেষ্টা attempt ' বা '..' কোনও প্রম্পট না করেই প্রত্যাখ্যান করা হয়, যেমন পসিক্স দ্বারা আদেশ দেওয়া হয়েছে।
সুতরাং, দেখে মনে হচ্ছে find
এই ক্ষেত্রে POSIX বিধিগুলিকে কেবল আঁকড়ে ধরেছে।
/var/log
এবং আপনি এটি মূলক হিসাবে সমস্ত চালককে সরিয়ে ফেলবেন এবং এটি বর্তমান ডিরেক্টরিটিও সরিয়ে ফেলবে তবে এই রুটটি মূলত চালাবেন?
man
পৃষ্ঠাটি find
বলে: "অপসারণ ব্যর্থ হলে একটি ত্রুটি বার্তা জারি করা হয়।" কেন কোনও ত্রুটি মুদ্রিত হয় না?
mkdir foo && cd foo && rmdir $(pwd)
। এটি মুছে ফেলা হচ্ছে .
(বা ..
) যা কাজ করে না।
Rmdir সিস্টেম কল EINVAL- এর সাথে ব্যর্থ হয় যদি এর তর্ক পথের শেষ উপাদানটি থাকে "."
। এটি http://pubs.opengroup.org/onlinepubs/009695399/function/rmdir.html এ নথিভুক্ত করা
হয়েছে এবং আচরণের যুক্তিটি হ'ল:
পথের নাম / ডট মুছে ফেলার অর্থটি অস্পষ্ট, কারণ মুখ্য ডিরেক্টরিতে ফাইল (ডিরেক্টরি) মুছে ফেলার নামটি স্পষ্ট নয়, বিশেষত কোনও ডিরেক্টরিতে একাধিক লিঙ্কের উপস্থিতিতে।
যদিও 林果 皞 এবং থমাস ইতিমধ্যে এটি সম্পর্কে ভাল উত্তর দিয়েছেন, আমি অনুভব করি যে তাদের উত্তরগুলি কেন প্রথমে এই আচরণ বাস্তবায়িত হয়েছিল তা ব্যাখ্যা করতে ভুলে গিয়েছিল ।
আপনার find . -delete
উদাহরণে বর্তমান ডিরেক্টরি মুছে ফেলা বেশ যৌক্তিক এবং বুদ্ধিমান শোনায়। তবে বিবেচনা করুন:
$ find . -name marti\*
./martin
./martin.jpg
[..]
মুছে ফেলা কি .
এখনও আপনার কাছে যৌক্তিক এবং বুদ্ধিমান মনে হয়?
খালি নয় এমন ডিরেক্টরি মুছে ফেলা একটি ত্রুটি - সুতরাং এর সাহায্যে আপনি এই তথ্যটি হারাতে পারবেন না find
(যদিও আপনি এটি করতে পারতেন rm -r
) - তবে আপনার শেলটির বর্তমান কাজ ডিরেক্টরিটি একটি ডিরেক্টরিতে সেট করা থাকবে যা কিছু বিভ্রান্তির দিকে পরিচালিত করবে এবং অবাক করা আচরণ:
$ pwd
/home/martin/test
$ rm -r ../test
$ touch foo
touch: cannot touch 'foo': No such file or directory
না বর্তমান ডিরেক্টরী মোছার কেবল ভাল ইন্টারফেস ডিজাইন এবং অন্তত বিস্ময় নীতিকে মেনে নেই।