This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
How to delete a directory and its contents in (POSIX) C?
This is in a standard Linux environment.
Thanks!
(I'm aware of rmdir but this isn't what I'm looking for.)
You'll want to traverse the directory tree, using nftw for file tree walk. For the rm -r example, use the flag FTW_DEPTH to process contents first, and check for FTW_D to use rmdir on directories rather than remove or unlink. Of course this doesn't guarantee you're allowed to remove things; that's generally decided by write persmission of the containing directory.
What's wrong with system("rm -rf");?
update: since commenters are showing with their comments that it's easy to miss the point, let me expand to clarify:
if (chdir(dirName) != 0)
return -1;
if (system("rm -rf .") != 0)
return -2;
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am rewriting the problem since it's not clearly understood as far as I see. I implement my own shell in C which needs to support all commands the original one does.
The problem is to execute all existing UNIX bash commands in C without using execvp() or system() functions which already let you do that easily.
To do that, I need to search all required directories which may consist any kind of UNIX commands. I just want to know that:
Do I really be sure that I support all possible UNIX commands in any distribution when I checked all directories in my PATH environment variable? (which becomes /bin/, /usr/bin/, /usr/local/bin in my machine)
I have also found a method which gets the full directory of a file you inserted called realpath() . But unfortunately, it returns (null) when I attempt to get the directory of the command inserted in my own shell.
What else do you suggest me to achieve this problem? As a last solution, does it make sense to search whole computer recursively from the root to find the command inserted?
If there's something unclear, please let me know to clarify. I would be very thankful if you could answer with a piece of example code and clear [on hold] tag in the question if you think it's clearly described from now.
Thanks in advance!
It is true that a UNIX executable can be absolutely anywhere, but in the context of a homework assignment, it doesn't make sense to search the entire filesystem. What your instructor probably wants you to do is implement the functionality of execvp yourself, using execv. What execvp does is, first, it looks to see if there is a slash in the command name. If there is, it passes the command and arguments directly to execv - it doesn't search. Otherwise, it iterates over the directories in PATH and checks whether the command is an executable in each. Crucially, it does NOT scan the contents of each directory; not only would that be very slow, it wouldn't even work under some conditions (such as a directory with --x permissions) Instead, it blindly calls execv with the pathname "$dir/$cmd". If that works, execv doesn't return. If it didn't work, and errno is set to ENOENT, it goes on to try the next directory in the path.
First, note that realpath() doesn't search anything, it just determines the absolute path of a given file.
There is no all possible UNIX command as you may think. At least any executable file can be considered as UNIX command, and executables are not necessarily the ones that have x right attached to it. Shell scripts may be executed by command like sh myscript even if executable access is not granted on it. Only binaries necessitate to have that attached right to be executed natively. So there is no true criterion that can help you. But you may have files that have x right and that are not executables!
A common usage is that executables are located in some directories /bin, /usr/bin, /usr/local/bin, and alike. Your shell has an environnement variable named PATH that contains list of directories where to search for command you specified freely on command line.
Anyway, if you choose a criterion to make an exhaustive search by yourself, say all files with x right then you can use command find like find some_starting_dir -perm +0111 to get all files that have x right somewhere.
If you want to program it then you may use either legacy readdir() function or the newer nftw() to make your own directory traversal. You will find many example of these even on SO.
This question already has answers here:
How can I use inverse or negative wildcards when pattern matching in a unix/linux shell?
(11 answers)
Closed 5 years ago.
I have a folder of audio files. Most are single sounds -- or soundSprites -- while some are several soundSprites concatenated into spriteLists. These spriteLists use a naming convention with a _SL added to the end of the file name. How can I create two arrays of soundSprites and spriteLists? I've tried using find to exclude the spriteLists like so:
soundSprites+=($(find . -maxdepth 1 ! -name "*_SL*"))
But this adds a ./ before every file name which I want to avoid. Instead of figuring out how to then iterate through the array and remove every ./ I can only assume there's an elegant solution to this that I'm simply unaware of.
Any help is greatly appreciated.
Don't use find here; this will fail for file names that contain characters the shell will use for word-splitting or pathname generation. Instead, use a pattern designed for pathname generation.
shopt -s extglob
soundSprites+=( !(*_SL*) )
With the information from the best answer of this question:
How can I use inverse or negative wildcards when pattern matching in a unix/linux shell?
you can do:
shopt extglob
soundSprites=(!(*_SL*))
This question already has answers here:
system("cd <path>") in a C program
(3 answers)
Closed 5 years ago.
I'm able to use popen to run just about any program, but apparently not cd:
#include <stdio.h>
void main() {
FILE *fp = popen("cd", "w");
pclose(fp);
}
I'd expect that to change directory to home but nothing happens. Changing to "r", or changing to e.g. "cd ~", "cd /", does not help. Using system has about the same result, i.e. works for anything but cd. So how is it done? The answers here don't work for me. Thank you.
cd is generally a shell internal command, NOT an executable.
Even if it were, in general no process can change another process's working directory, so it would change the cwd for the "cd" process and then upon exit it'd be gone.
How can I remove opened file in linux?
In shell I can do this:
rm -rf /path/to/file_or_directory
But how can I do it in C?
I don't want to using system() function.
I have seen unlink and remove method but it's haven't any flags to set force deletion.
The unlink and remove functions force deletion. The rm command is doing extra checks before it calls one of those functions. But once you answer y, it just uses that function to do the real work.
Well, I hope this answers your question.. This program searches the current directory for the filename, you have to add the feature of opening a different directory, which shouldn't be too hard... I don't understand the last line of your question, can you elaborate? But flags aren't necessary for remove and unlink (They force delete)...
#include<stdio.h>
int main()
{
int status;
char file_name[25];
printf("Enter the name of file you wish to delete\n");
fgets(file_name,25,stdin);
status = remove(file_name);
if( status == 0 )
printf("%s file deleted successfully.\n",file_name);
else
{
printf("Unable to delete the file\n");
perror("Error");
}
return 0;
}
To perform a recursive removal, you have to write a moderately complicated program which performs a file system walk. ISO C has no library features for this; it requires platform-specific functions for scanning the directory structure recursively.
On POSIX systems you can use opendir, readdir and closedir to walk individual directories, and use programming language recursion to handle subdirectories. The functions ftw and its newer variant nwft perform an encapsulated file system walk; you just supply a callback function to process the visited paths. nftw is better because it has a flags argument using which you can specify the FTW_DEPTH flag to do the search depth first: visit the contents of a directory before reporting the directory. That, of course, is what you want for recursive deletion.
On MS Windows, there is FindFirstFile and FindNextFile to cob together a recursive traversal.
About -f, that only suppresses certain checks done by the rm program above and beyond what the operating system requires. Without -f, you get prompted if you want to delete a read-only file, but actually, in a Unix-like system, only the directory write permission is relevant, not that of the file, for deletion. The remove library function doesn't have such a check.
By the way, remove is in ISO C, so it is platform-independent. On POSIX systems, it calls rmdir for directories and unlink for other objects. So remove is not only portable, but lets you not worry about what type of thing you're deleting. If a directory is being removed, it has to be empty though. (Not a requirement of the remove function itself, but of mainstream operating systems that support it).
remove or unlink is basically equivalent to rm -f already--that is, it removes the specified item without prompting for further input.
If you want something equivalent to rm -r, you'll need to code up walking through the directory structure and deleting items individually. Boost Filesystem (for one example) has code to let you do that fairly simply while keeping the code reasonably portable.
I want to clean all files in a directory on Linux (not deleteing them, only clear their content)
I need to do it in C.
Actually, you really don't need to do it in C. UNIX includes tools that can just about do any task that you want.
find . -type f -exec cp /dev/null {} ';'
That particular snippet above will find all files under the current directory and attempt to copy the null device to it, effectively truncating the file to 0 bytes.
You can change the starting (top level) directory, restrict names (with -name '*.jpg' for example) and even restrict it to the current directory (no subdirectories) with -maxdepth 0.
There are many other options with find that you can discover by entering man find into your command line shell. Just don't enter it into Google, you may get more than you bargained for :-)
If the need to use C is an absolutely non-negotiable one, I would still do it this way but with:
system ("find . -type f -exec cp /dev/null {} ';'");
I'm not keen on re-writing software that someone's already put a bucketload of effort into providing for free :-)
If, after my advice, you still want to do it the hard way, you need to look into opendir, readdir and closedir for processing directories, then just use fopen in write mode followed by fclose on each candidate file.
If you want to navigate whole directory structures rather than just the current directory, you'll have to detect directories from readdir and probably recurse through them.
scandir to list them, then for every file:
fopen(, w+)
fstat to get the size
fwrite the whole file with zeroes? (this is what you mean by clear?)
fclose
A nice shell variant would be: shred -z directory/*
In Bash:
for i in directory/*; do > $i; done
This will preserve ownership and permissions of the file.
Don't do shell work in C! Save a huge amount of time by using the best tool for the job. If this is homework, mark it as such.
You can open the file in write mode and then close it.