কেন খুঁজে পাচ্ছে না। - বর্তমান ডিরেক্টরি মুছে ফেলুন?


22

আমি আশা করব

find . -delete

বর্তমান ডিরেক্টরি মুছতে, তবে তা হয় না। কেন না?


3
সম্ভবত সম্ভবত বর্তমানের ডিরেক্টরিটি সরিয়ে ফেলা ভাল ধারণা হবে না।
আলেকজ মাগুরা

একমত - ডিফল্ট আচরণ আমি, কিন্তু এটা, সঙ্গে যেমন সঙ্গতিপূর্ণ নয় find . -print
এমব্রোশি

@ আলেকজমগুরা যদিও আমি সহানুভূতি প্রকাশ করি, তবুও বর্তমান ডিরেক্টরিটি অপসারণের জন্য একটি উন্মুক্ত ফাইল অপসারণের চেয়ে আলাদা হওয়া উচিত বলে আমি মনে করি না। কোনও রেফারেন্স উপস্থিত না হওয়া পর্যন্ত অবজেক্টটি বেঁচে থাকবে এবং তারপরে জঞ্জাল সংগ্রহ করা হবে। আপনি cd ..; rm -r dirবেশ স্পষ্ট শব্দার্থক দিয়ে অন্য শেলটি দিয়ে করতে পারেন ...
রোমানো

@ রুমানো এটি সত্য: এটি কেবলমাত্র এমন কিছু যা আমি নীতির ভিত্তিতে না করি: কেবল একটি ডিরেক্টরিতে যান এবং তারপরে বর্তমান ডিরেক্টরিটি মুছুন। এটি এত বড় ব্যাপার কেন আমি পুরোপুরি নিশ্চিত নই - যদিও বর্তমান ডিরেক্টরিটি নিয়ে আমার কিছু দুর্ভাগ্য হয়েছে যেমন আপেক্ষিক পথগুলি আর কাজ করে না, তবে আপনি সর্বদা একটি নিখুঁত পথ ব্যবহার করে বেরিয়ে যেতে পারেন - তবে আমার কিছু অংশ কেবল বলেছেন যে এটি সাধারণভাবে ভাল ধারণা নয়।
আলেকজ মাগুরা

উত্তর:


29

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করতে হবে।

'..' ডিরেক্টরিটি তার প্রথম এন্ট্রি '..' পড়ে এবং চিরকালের জন্য লুপ করে।

উপসংহার:

  1. জিএনইউ * বিএসডি-তে ইউটিলিটির findutilsসাথে সামঞ্জস্য করার চেষ্টা করুন ।find

  2. find* বিএসডি-তে ইউটিলিটি অভ্যন্তরীণভাবে rmdirপসিএক্স-কমপ্লায়েন্ট সি ফাংশন ব্যবহার করে যা বিন্দু / বিন্দু বিন্দু অনুমোদিত নয়।

  3. rmdirডট / ডট-ডটকে অনুমতি না দেওয়ার কারণ হ'ল চক্রীয় ফাইল সিস্টেমের পথগুলি প্রতিরোধ করা।

  4. কে অ্যান্ড আর রচিত সি প্রোগ্রামিং ল্যাঙ্গুয়েজে ডট / ডট-ডট কীভাবে চিরকালের লুপ প্রোগ্রামে নিয়ে যাবে তার উদাহরণ দেখায়।


16

কারণ আপনার findআদেশটি .ফলাফল হিসাবে ফিরে আসে returns এর তথ্য পৃষ্ঠা থেকে rm:

যার সর্বশেষ ফাইলের নাম উপাদানটি এমন কোনও ফাইল সরানোর কোনও প্রচেষ্টা attempt ' বা '..' কোনও প্রম্পট না করেই প্রত্যাখ্যান করা হয়, যেমন পসিক্স দ্বারা আদেশ দেওয়া হয়েছে।

সুতরাং, দেখে মনে হচ্ছে findএই ক্ষেত্রে POSIX বিধিগুলিকে কেবল আঁকড়ে ধরেছে।


2
যেমনটি হওয়া উচিত: পসিক্স কিং, প্লাস বর্তমান ডিরেক্টরি মুছে ফেলা প্যারেন্ট অ্যাপ্লিকেশনটির উপর নির্ভর করে কিছু বড় সমস্যা সৃষ্টি করতে পারে এবং কী নয়। যদি বর্তমান ডিরেক্টরিটি থাকে /var/logএবং আপনি এটি মূলক হিসাবে সমস্ত চালককে সরিয়ে ফেলবেন এবং এটি বর্তমান ডিরেক্টরিটিও সরিয়ে ফেলবে তবে এই রুটটি মূলত চালাবেন?
আলেকজ মাগুরা

1
এটি একটি ভাল তত্ত্ব, তবে manপৃষ্ঠাটি findবলে: "অপসারণ ব্যর্থ হলে একটি ত্রুটি বার্তা জারি করা হয়।" কেন কোনও ত্রুটি মুদ্রিত হয় না?
এমব্রোশি

1
@AlexejMagura বর্তমান ডিরেক্টরী মুছে ফেলার পদ্ধতি সাধারণভাবে কাজ করে জরিমানা: mkdir foo && cd foo && rmdir $(pwd)। এটি মুছে ফেলা হচ্ছে .(বা ..) যা কাজ করে না।
তাভিয়ান বার্নস

4

Rmdir সিস্টেম কল EINVAL- এর সাথে ব্যর্থ হয় যদি এর তর্ক পথের শেষ উপাদানটি থাকে "."। এটি http://pubs.opengroup.org/onlinepubs/009695399/function/rmdir.html এ নথিভুক্ত করা হয়েছে এবং আচরণের যুক্তিটি হ'ল:

পথের নাম / ডট মুছে ফেলার অর্থটি অস্পষ্ট, কারণ মুখ্য ডিরেক্টরিতে ফাইল (ডিরেক্টরি) মুছে ফেলার নামটি স্পষ্ট নয়, বিশেষত কোনও ডিরেক্টরিতে একাধিক লিঙ্কের উপস্থিতিতে।


2

কল করা হচ্ছে rmdir(".")যখন আমি এটা চেষ্টা একটি সিস্টেম কল কাজ করে নি হিসাবে, তাই কোনও উচ্চ স্তরের টুল সফল করতে পারেন।

আপনাকে অবশ্যই ডিরেক্টরিটির আসল নামটির মাধ্যমে এটির নাম না দিয়ে মুছতে হবে .


1

যদিও 林果 皞 এবং থমাস ইতিমধ্যে এটি সম্পর্কে ভাল উত্তর দিয়েছেন, আমি অনুভব করি যে তাদের উত্তরগুলি কেন প্রথমে এই আচরণ বাস্তবায়িত হয়েছিল তা ব্যাখ্যা করতে ভুলে গিয়েছিল ।

আপনার 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

না বর্তমান ডিরেক্টরী মোছার কেবল ভাল ইন্টারফেস ডিজাইন এবং অন্তত বিস্ময় নীতিকে মেনে নেই।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.