Как переместить файл из одной папки в другую папку в Linux

Как переместить конкретный файл из одной папки в другую?

Что я пробовал,

#include <stdio.h>

int main() {
    FILE *tFile;
    if (tFile != NULL)
        tFile = NULL;
    if ((tFile = fopen("TempFile.txt", "rw")) == NULL) {
        return -1;
    }

    mv("TempFile.txt", "../MST");

    printf("Done Succesfully\n");
    return 0;
}

Ошибка :

test.c:17:2: warning: no newline at end of file
/tmp/ccKLWYNa.o(.text+0x5e): In function `main':
: undefined reference to `mv'
collect2: ld returned 1 exit status

Пожалуйста, помогите мне, как я могу это сделать.


person user2845185    schedule 23.11.2013    source источник
comment
СОВЕТ: mv — это команда оболочки.   -  person devnull    schedule 23.11.2013
comment
Иногда я удивляюсь, почему «нет новой строки в конце файла» для основного файла модулей компиляции является предупреждением по умолчанию, а «неявное объявление функции» — нет.   -  person Jonas Schäfer    schedule 23.11.2013
comment
@devnull... Могу ли я использовать его в своей программе, не создавая другого процесса?   -  person user2845185    schedule 23.11.2013
comment
есть system() для вызова mv, но на самом деле вам следует просто использовать rename   -  person cnd    schedule 23.11.2013
comment
@ Хизер ... Я не хочу создавать для этого еще один процесс.   -  person user2845185    schedule 23.11.2013
comment
Кстати, правильная терминология в Linux и Posix - это каталог, а не папка.   -  person Basile Starynkevitch    schedule 23.11.2013
comment
@JonasWielicki: пожалуйста, поместите в GCC bugzilla предложение о таких предупреждениях.   -  person Basile Starynkevitch    schedule 23.11.2013
comment
@BasileStarynkevitch Извините, я не знаю, уместно ли и что. Я создаю свое программное обеспечение с помощью -Wall -Wextra -Werror -Wno-unused-parameter, и я думаю, что это должно быть по умолчанию, поэтому я немного предвзят;). Я действительно не могу себе представить, почему люди будут использовать неявно объявленные функции, но, возможно, в этом есть смысл.   -  person Jonas Schäfer    schedule 24.11.2013
comment
Я склонен с вами согласиться, но такое мнение недостаточно выражено в GCC. Поэтому, пожалуйста, заполните багзиллу!   -  person Basile Starynkevitch    schedule 24.11.2013


Ответы (1)


Вам действительно следует прочитать Advanced Linux Programming и системные вызовы(2)

Чтобы переместить (из C) файл из одного места в другое в той же файловой системе, просто используйте переименовать(2) системный вызов.

По крайней мере, для вашего конкретного примера вам нужно будет закодировать:

char* srcpath = "TempFile.txt"; // assume it is a variable path
char destpath[1024];
snprintf (destpath, sizeof(destpath), "../MST/%s", srcpath);
if (rename (srcpath, destpath)) {
   // something went wrong
   if (errno == EXDEV) {
      // copy data and meta data 
   } else { perror("rename"); exit(EXIT_FAILURE); };
} 
else { // the rename succeeded
}

Если вы действительно хотите mv TempFile.txt ../MST/TempFile.txt только для TempFile.txt, вы можете просто вызвать rename("TempFile.txt", "../MST/TempFile.txt") и обработать случаи ошибок, как я предлагаю. Если вы уверены, что ../MST/лежит в той же файловой системе, что и ., то EXDEV не должно происходить и вам не нужно особо с этим разбираться (но нужно обрабатывать ошибки).

Если вы хотите переместить файл между двумя разными файловыми системами, вам нужно скопировать данные (и, возможно, некоторые метаданные) самостоятельно (а затем удалить, например, с помощью удалить(2)) исходный файл). Вы можете обнаружить эту ситуацию различными способами: вы можете просто попробовать rename и если errno (см. errno(3)) – это EXDEV вам нужно скопировать файл. Или вы можете использовать stat(2) для запроса источника метаданные файла (и целевого каталога) - например. его размер и файловая система.

Конечно, вам нужно понимать, что такое файлы в Linux (или Posix), в частности, что такое inode.... См. inode(7) и учетные данные(7)

Вы могли бы использовать system с /bin/mv (но будьте осторожны со странными символами, такими как пробелы или точки с запятой, в путях к файлам, вам нужно экранировать их, чтобы избежать внедрение кода), очевидно, вы этого не хотите.

Вам следует поиграть с strace(1) (или, возможно, также ltrace) на mv в различных ситуациях, чтобы понять, что он делает. Кроме того, изучите исходный код GNU coreutils, который предоставляет /bin/mv, особенно в mv.c ...

Некоторые дополнительные библиотеки C или C++ могут предоставить вам функции для перемещения файлов (в одной и той же файловой системе они должны выполнять rename, в других файловых системах они копируют данные исходного файла и, возможно, некоторые метаданные и отсоединяют источник, поэтому не могут быть атомарными ), например в C g_file_move (из Gio с Glib из Gnome) или на C++ copy_file, за которым следует remove в Boost и т.д. и т.п....

PS. Для временных файлов см. tmpfile(3), mkstemp(3) и т. д.

person Basile Starynkevitch    schedule 23.11.2013