LINUX.ORG.RU

удалить все симлинки в бакапе?

 


0

1

Доброго всем.

Делаю время от времени бакапы да домашнем компе да два диска. Столкнулся с проблемой. Раньше не с ln -s делал симлинки, а с миднайта. А он полный путь пишет. Какая команда найти битые симлинки? Я уже понял, что нельзя так делать, что просто контал-икс-контал-с. но накопилось много. И как с Кубунты на Дебиан начал переползать… в самой системе то ничего, а в бакапах ссылки по другому пути идут (имя пользователя) PS://надеюсь мой пьяный вопрос поймет кто-нибудь

★★★

Зачем удалять? Их исправлять надо. Если симлинк есть, но чуть битый и его понятно как исправить (когда столкнёшься) - это лучше, чем когда он вообще потерялся.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от anonymous

Вот честно бред все эти чат гпт - игрушка. Накидывать формулировки для последующей обработки, может.

Поиск по шаблону - пожалуйста.

А точные ответы - нет.

Своя голова лучше и знания в ней отложатся при осознанном поиске.

anonymous
()

Программа для фикса симлинков как тебе надо (код ниже). Сохраняешь как fixlinks.c, компилируешь (gcc -Wall -o fixlinks fixlinks.c), запускаешь:

./fixlinks --relative /новый/путь /старый/путь
Она рекурсивно просмотрит все файлы внутри директории /новый/путь и если найдёт среди них симлинки, начинающиеся на /старый/путь - превратит их в относительные как будто вместо /старый/путь они начинаются с /новый/путь. Например если на старой системе у тебя было /home/username1 а на новой ты это всё перенёс в /home/newuser то надо так:
./fixlinks --relative /home/newuser /home/username1
или можно просто исправить ссылки, оставив их абсолютными:
./fixlinks --absolute /home/newuser /home/username1

/* (c) firk 2024; feel free to use this code for anything */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>

static char const *basepath, *oldbasepath;
static size_t bplen, obplen, inclen;
static int is_relative;

typedef struct { char *s; size_t len, sz; } dynstr;
static dynstr path, lpath, nlpath;
static void dynstr_need_len(dynstr *ds, size_t len) {
  size_t newsz;
  if(len<ds->sz) return;
  newsz = len*2+1000;
  if(newsz<=len || !(ds->s = realloc(ds->s,newsz))) { fprintf(stderr, "out of memory\n"); exit(-1); }
  ds->sz = newsz;
}

static char const * fix_slashes(char const *title, char *p) {
  size_t len;
  char *dst;
  len = strlen(p);
  if(!len || *p!='/') { fprintf(stderr, "%s should be absolute path\n", title); exit(-1); }
  if(strstr(p,"//")) { fprintf(stderr, "%s should not contain \"//\"\n", title); exit(-1); }
  len += 2;
  if(len<=2 || !(dst = malloc(len))) { fprintf(stderr, "out of memory"); exit(-1); }
  len -= 2;
  bcopy(p, dst, len);
  if(dst[len-1]!='/') dst[len++] = '/';
  dst[len] = 0;
  return dst;
}

static void path_append_dir(size_t savelen, char const *name) {
  size_t add;
  size_t len;
  add = strlen(name);
  len = savelen + add + 1;
  if(len<=savelen || len<=add || len<=1) { fprintf(stderr, "out of memory\n"); exit(-1); }
  dynstr_need_len(&path, len);
  bcopy(name, path.s+savelen, add);
  path.s[savelen+add] = '/';
  path.s[savelen+add+1] = 0;
  path.len = savelen+add+1;
}



extern char const * my_readlinkat(int dfd, char const *name, size_t sz) {
  ssize_t rsz;
  if(sz<256) sz = 256;
  dynstr_need_len(&lpath, sz);
  while(1) {
    if((rsz = readlinkat(dfd, name, lpath.s, lpath.sz))<0) return NULL;
    if(lpath.sz>(size_t)rsz) {
      lpath.s[rsz] = 0;
      lpath.len = rsz;
      return lpath.s;
    }
    dynstr_need_len(&lpath, lpath.sz);
  }
}

static void handle_symlink(int dfd, char const *n, struct stat const *sb) {
  char const *lnk, *pp, *pl, *nl;
  char *newlink;
  size_t lnklen, newlen, level, j;
  lnk = my_readlinkat(dfd, n, (sb->st_size>256)?sb->st_size:256);
  if(!lnk) {
    fprintf(stderr, "readlink(%s%s) error %d (%s)\n", path.s, n, errno, strerror(errno));
    return;
  }
  lnklen = strlen(lnk);
  if(*lnk!='/' || strncmp(lnk,oldbasepath,obplen) || lnk[obplen]!='/' && lnk[obplen]) {
    printf("not changing symlink \"%s%s\" -> \"%s\"\n", path.s, n, lnk);
    fflush(stdout);
    return;
  }
  if(!is_relative) {
    newlen = lnklen + inclen;
    if(newlen<lnklen || newlen<inclen) { fprintf(stderr, "out of memory"); exit(-1); }
    dynstr_need_len(&nlpath, newlen);
    bcopy(basepath, nlpath.s, bplen);
    bcopy(lnk+obplen, nlpath.s+bplen, lnklen-obplen+1);
    nl = nlpath.s;
  } else {
    pp = path.s+bplen;
    pl = lnk+obplen;
    while(1) {
      assert(*pp=='/');
      if(!*pl || *pl=='/' && !pl[1]) break;
      assert(*pl=='/');
      for(j=1; pp[j] && pl[j] && pp[j]!='/' && pl[j]!='/' && pp[j]==pl[j]; j++);
      if(pp[j]!='/' || pl[j]!='/' && pl[j]) break;
      pp+=j; pl+=j;
    }
    assert(*pp=='/');
    assert(!*pl || *pl=='/');
    for(pp++,level=0; *pp; pp++) if(*pp=='/') level++;
    if(!level) {
      if(!*pl || !pl[1]) nl = "."; else nl = pl+1;
    } else {
      lnklen = strlen(pl);
      newlen = lnklen + level*3;
      if(newlen<lnklen || (newlen-lnklen)/3!=level) { fprintf(stderr, "out of memory"); exit(-1); }
      dynstr_need_len(&nlpath, newlen);
      for(j=0;j<level;j++) { nlpath.s[j*3] = '.'; nlpath.s[j*3+1] = '.'; nlpath.s[j*3+2] = '/'; }
      bcopy(pl, nlpath.s+level*3-1, lnklen+1);
      nl = nlpath.s;
    }
  }
  printf("replacing symlink \"%s%s\" -> \"%s\" -> \"%s\"\n", path.s, n, lnk, nl);
  fflush(stdout);
  if(unlinkat(dfd, n, 0)<0) { fprintf(stderr, "unlink(%s%s) error %d (%s)\n", path.s, n, errno, strerror(errno)); return; }
  if(symlinkat(nl, dfd, n)<0) { fprintf(stderr, "symlink(..., %s%s) error %d (%s)\n", path.s, n, errno, strerror(errno)); return; }
}

static void recurse_dir(int dfd, int level) {
  DIR *dp;
  struct dirent *de;
  size_t savelen;
  char const *n;
  struct stat sb;
  int fd;
  savelen = path.len;
  if(!(dp=fdopendir(dfd))) {
    fprintf(stderr, "fdopendir(%s) error %d (%s)\n", path.s, errno, strerror(errno));
    close(dfd);
    return;
  }
  while(errno=0,de=readdir(dp)) {
    n = de->d_name;
    if(*n=='.' && (!n[1] || n[1]=='.' && !n[2])) continue;
    if(fstatat(dfd, n, &sb, AT_SYMLINK_NOFOLLOW)<0) { fprintf(stderr, "lstat(%s%s) error %d (%s)\n", path.s, n, errno, strerror(errno)); continue; }
    if(S_ISLNK(sb.st_mode)) { handle_symlink(dfd,n,&sb); continue; }
    if(S_ISDIR(sb.st_mode)) {
      if((fd = openat(dfd, n, O_DIRECTORY|O_NOFOLLOW))<0) { fprintf(stderr, "open dir \"%s%s\" error %d (%s)\n", path.s, n, errno, strerror(errno)); return; }
      path_append_dir(savelen, n);
      recurse_dir(fd, level+1);
      path.s[path.len = savelen] = 0;
    }
  }
  if(errno) fprintf(stderr, "readdir(%s) error %d (%s)\n", path.s, errno, strerror(errno));
  closedir(dp);
}

int main(int argc, char **argv) {
  int fd;
  size_t len;
  if(argc!=4) {
  usage:
    fprintf(stderr, "Usage: fixlinks {--absolute|--relative} <basepath> <oldbasepath>\n");
    return -1;
  }
  if(!strcmp(argv[1],"--absolute")) is_relative = 0;
  else if(!strcmp(argv[1],"--relative")) is_relative = 1;
  else goto usage;
  basepath = fix_slashes("basepath", argv[2]);
  oldbasepath = fix_slashes("oldbasepath", argv[3]);
  bplen = strlen(basepath)-1;
  obplen = strlen(oldbasepath)-1;
  inclen = (obplen<bplen)?bplen-obplen:0;
  if(!(path.s = strdup(basepath))) { fprintf(stderr, "out of memory\n"); return -1; }
  path.len = strlen(path.s);
  path.sz = path.len + 1;
  if((fd = open(basepath, O_DIRECTORY|O_NOFOLLOW))<0) {
    fprintf(stderr, "open dir \"%s\" error %d (%s)\n", basepath, errno, strerror(errno));
    return -1;
  }
  recurse_dir(fd,0);
  return 0;
}
firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от anonymous

Если тебе весело - круто. Мой подход изучения материала другой. Не тот, что у тебя.

Тебе чатгпт даёт подсказки, но ты не очень представляешь откуда и как это всё связано.

Я может быть дольше прорабатываю материал, но в процессе изучения я осознанно ищу конкретные вещи и в голове создаются связи, которыми потом можно оперировать и связи эти подкрепляются с каждой найденной и прочитанной информацией, самое главное понятой.

Тебе чатгпт может сразу накидат терминов, ты даже можешь начать раньше пробовать их применять, но понимая как они связаны у тебя не будет. И как только ты столкнёшься с проблемой из-за отсутствия понимания - поймёшь. Что чатгпт - это как хэш функция, которая тебе по тегам выдаёт некоторый набор информации, где упоминаются фразы и термины, но не как они связаны между собой.

Если ты привык запихивать себе в голову кашу - вперёд, ешь.

anonymous
()
Ответ на: комментарий от anonymous

ты шиз что ли? чатгпт это поисковик на стероидах, там где ты полдня будешь долбиться с гуглом и продираться сквозь мудаков на форумах - я уже через 5 секунд получу ответ, причём на такой вопрос, который нагуглить невозможно или придётся опять же копаться полдня, чтобы склеить ответ из кусочков, раскиданных по всему интернету

впрочем, зачем я трачу время на неадекватов

anonymous
()
Ответ на: комментарий от anonymous

Объявления это метаданные к алгоритму, как с точки зрения компилятора, так и с точки зрения программиста. Они не производят никаких действий сами по себе.

firkax ★★★★★
()
Ответ на: комментарий от anonymous

впрочем, зачем я трачу время на неадекватов

Ты знаешь, самое интересное моё мнение тут совпадает с твоим на все 100%.

Но дам совет - учись формулировать мысли и правильно составлять запросы в поисковую систему.

И ещё всё зависит от сложности возникающих вопросов. Если у тебя относительно простые вопросы - ну может быть.

Удачи в использовании.

anonymous
()
Ответ на: комментарий от anonymous

поисковик на стероидах

Есть одно отличие - этот «поисковик» умеет врать и выдумывать ерунду (ну и ошибается понятное дело). Но по таким простым вопросам как поиск и удаление битых ссылок даёт сразу правильный ответ.

sergej ★★★★★
()
Ответ на: комментарий от sergej

этот «поисковик» умеет врать и выдумывать ерунду (ну и ошибается понятное дело)

есть такое, но эта проблема больше раздута, чем актуальна

у меня он галлюцинирует крайне редко, в 1 случае из 100 или даже ещё реже

примерно в 1 случае из 10 - даёт ошибочный ответ, но тогда просто говоришь ему, что не работает, и он поправляется, хоть иногда и не с первого раза

в любом случае, это на порядки быстрее, чем искать ответы на форумах, особенно с учётом того, как много пасётся на форумах стервозных мудаков, которые любят по-бабски трахать мозги вместо того чтобы ответить на вопрос

anonymous
()
Ответ на: комментарий от anonymous

Ещё есть один фактор, который ты может не учитываешь.

Лично важен не только ответ на вопрос как что-то сделать, а ещё почему нужно делать так и как ещё можно сделать и почему так работает.

Т.е. важно не просто как, а ещё и почему.

Поэтому я в первую очередь буду читать документацию и анализировать, чем прост в лоб пробовать применять готовые ответы, будь то чатгпт или ответ на форуме.

Если тебя устраивают просто ответы как что-то сделать, а ответ почему нужно делать так, а не иначе и как можно сделать ещё или вообще нужно пересмотреть подход тебя не интересует - используй чатгпт.

Но меня это не устраивает.

У меня другой подход к решению проблем и изучению материала.

Вообще, интересно наблюдать когда у человека что-либо противоречит с его мировосприятием он называет все, что не укладывается в его картину мира неадекватностью.

Я часто встречаю, что что-либо отличается от моего восприятия мира или знаний и в этом случае начинаю разбираться, если мне это важно.

anonymous
()
Ответ на: комментарий от anonymous

Клован, иди уже попробуй чатгпт. Если бы ты пробовал, ты бы знал, что он как раз объясняет, почему это так, а не иначе. Если спросишь, нельзя ли по-другому - он предложит другой вариант и опять же расскажет, как это работает. Он всегда по дефолту подробно объясняет, так что порой приходится просить его прикрутить фонтан и отвечать кратко.

Сука да откуда столько дебилоидов лезет, нихера не знают и не пробуют, но сука сидят гонят пургу с умным видом. Шизы долбаные.

anonymous
()
Ответ на: комментарий от anonymous

Ба-а-а, да твоя личность раскрывается во всей красе, у тебя комплексы, я тебе скажу для поднятия твоей самооценки, ну да, ты молодец, по некоторым моментам ты мне просветил.

Попробую, посмотрю, мой опыт больше с яндекс гпт.

Спасибо, ты молодец знаешь, можешь. Не принижай свои возможности, всё будет хорошо.

Но понимаешь какая вещь я привык делать выводы сам, а не получать готовые ответы.

Но спасибо за ответы.

Только успокойся. Не нервничай, я тебя услышал.

anonymous
()
Ответ на: комментарий от anonymous

А кто тебе сказал, что я что-то пытаюсь корчить? Я не психолог. Но это мой вывод.

Когда человек начинает оскорблять кого-то, доказывая свои выводы - это лишь показатель его низкой самооценки.

Это мой вывод и я тебе его высказал. Возможно он ошибочный, но исходя их имеющихся данных он такой.

Не переживай ты так.

anonymous
()
Ответ на: комментарий от anonymous
Вы (3:12:16 AM): Что означает, когда человек при доказывании своей правоты переходит к оскорблениям
ChatGPT (3:12:20 AM): Когда человек при доказывании своей правоты переходит к оскорблениям, это чаще всего означает, что он не в состоянии или не желает продолжать обсуждение на рациональном уровне и переходит на уровень личных атак, чтобы попытаться дискредитировать оппонента или заставить его замолчать. Это часто происходит из-за несостоятельности аргументов или из-за эмоциональных всплесков. Оскорбления в дискуссии редко способствуют конструктивному диалогу и могут привести к нарушению аргументации. Лучше всегда стремиться к уважительному и аргументированному общению вне зависимости от мнений и взглядов.КопироватьПоделиться с друзьями
Вы (3:13:16 AM): Может ли быть причиной низкая самооценка?
ChatGPT (3:13:21 AM): Да, низкая самооценка может быть одной из причин, по которой человек переходит к оскорблениям при доказывании своей правоты. Люди с низкой самооценкой могут испытывать неуверенность в себе, боязнь быть неправыми или неудачи, и использовать оскорбления как защитный механизм или способ утверждения своей значимости. Иногда они могут пытаться компенсировать свои внутренние комплексы или недостатки за счёт агрессивного поведения.

Важно понимать, что агрессия и оскорбления в дискуссиях обычно не решают проблемы и не улучшают ситуацию. Лучше постараться улучшить свою самооценку, развивать навыки общения и решения конфликтов в конструктивном направлении. Вместо оскорблений можно использовать уважительный подход к обсуждению разногласий и стремиться к взаимопониманию.КопироватьПоделиться с друзьями

Слушай, мне понравилось, вещь!

Поэтому, предлагаю продолжать в конструктивном ключе, если есть желание.

anonymous
()