/*
* List files with date, type and size.
*
* Compile this file with Visual Studio and run the produced command in
* console with a directory name argument. For example, command
*
* dir "C:\Users\User 1\Documents"
*
* might output something like
*
* Directory of c:\Users\User 1\Documents
*
* 2021-06-06 20:04
.
* 2021-07-20 13:42 ..
* 2020-06-21 15:00 402 desktop.ini
* 2020-06-21 15:00 Omat kuvatiedostot
* 2020-06-21 15:00 Omat musiikkitiedostot
* 2020-06-21 15:00 Omat videotiedostot
* 2018-12-21 18:34 Visual Studio 2017
* 3 File(s) 402 bytes
* 7 Dir(s)
*
* The dir command provided by this file is only an example: the command
* does not have any fancy options.
*
* Copyright (C) 2006-2012 Toni Ronkko
* This file is part of dirent. Dirent may be freely distributed
* under the MIT license. For all details and documentation, see
* https://github.com/tronkko/dirent
*/
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#include
#include
#include
#define ERR_MSG_LEN 256
static void list_directory(const char* dirname);
static void fail(const char* dirname);
static int _main(int argc, char *argv[]);
static int
_main(int argc, char* argv[])
{
/* For each directory in command line */
int i = 1;
while (i < argc) {
list_directory(argv[i]);
i++;
}
/* List current working directory if no arguments on command line */
if (argc == 1)
list_directory(".");
return EXIT_SUCCESS;
}
/* List files and file sizes in directory */
static void
list_directory(const char* dirname)
{
char path[PATH_MAX + 2];
char *p = path;
char *end = &path[PATH_MAX];
/* Copy directory name to path */
const char *src = dirname;
while (p < end && *src != '\0') {
*p++ = *src++;
}
/* Get final character of directory name */
char c = (path < p ? p[-1] : ':');
/* Append directory separator if not already there */
if (c != ':' && c != '/' && c != '\\')
*p++ = '/';
/* Print directory name to screen */
printf("Directory of %s\n\n", dirname);
/* Open directory stream */
DIR *dir = opendir(dirname);
if (!dir) {
/* Could not open directory */
fprintf(stderr,
"Cannot open %s (%s)\n", dirname, strerror(errno));
exit(EXIT_FAILURE);
}
/* Loop through file names */
int filecount = 0;
int dircount = 0;
long long bytecount = 0;
struct dirent *ent;
while ((ent = readdir(dir)) != NULL) {
/* Append file name to path */
char *q = p;
src = ent->d_name;
while (q < end && *src != '\0') {
*q++ = *src++;
}
*q = '\0';
/* Get file properties such as size and modification time */
struct stat stbuf;
if (stat(path, &stbuf) == /*error*/-1) {
fail(path);
}
/* Get file type from stat buffer */
const char *type;
if (S_ISDIR(stbuf.st_mode)) {
/* Directory */
type = "";
} else if (S_ISREG(stbuf.st_mode)) {
/* Regular file */
type = "";
} else if (S_ISLNK(stbuf.st_mode)) {
/* Link */
type = "";
} else {
/* Named pipe, socket, character device or else */
type = "";
}
/* Get last modification date as a string */
struct tm *tp = localtime(&stbuf.st_mtime);
char mtime[40];
sprintf(mtime, "%04d-%02d-%02d %02d:%02d",
tp->tm_year + 1900,
tp->tm_mon + 1,
tp->tm_mday,
tp->tm_hour,
tp->tm_min);
/* Get file size as a string */
char size[40];
if (S_ISREG(stbuf.st_mode)) {
sprintf(size, "%lld", (long long) stbuf.st_size);
} else {
size[0] = '\0';
}
/* Output file info */
printf("%-20s %-5s %12s %s\n",
mtime, type, size, ent->d_name);
/* Compute totals */
if (S_ISREG(stbuf.st_mode)) {
filecount++;
bytecount += (long long) stbuf.st_size;
}
if (S_ISDIR(stbuf.st_mode)) {
dircount++;
}
}
/* Output sums */
printf("%20d File(s) %12lld bytes\n", filecount, bytecount);
printf("%20d Dir(s)\n", dircount);
}
/* Print error message and exit with error condition */
static void
fail(const char* msg)
{
/* Output error message */
perror(msg);
/* Exit the program immediately */
exit(EXIT_FAILURE);
}
/* Stub for converting arguments to UTF-8 on Windows */
#ifdef _MSC_VER
int
wmain(int argc, wchar_t *argv[])
{
/* Select UTF-8 locale */
setlocale(LC_ALL, ".utf8");
SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
/* Allocate memory for multi-byte argv table */
char **mbargv;
mbargv = (char**) malloc(argc * sizeof(char*));
if (!mbargv) {
puts("Out of memory");
exit(3);
}
/* Convert each argument in argv to UTF-8 */
for (int i = 0; i < argc; i++) {
size_t n;
wcstombs_s(&n, NULL, 0, argv[i], 0);
/* Allocate room for ith argument */
mbargv[i] = (char*) malloc(n + 1);
if (!mbargv[i]) {
puts("Out of memory");
exit(3);
}
/* Convert ith argument to utf-8 */
wcstombs_s(NULL, mbargv[i], n + 1, argv[i], n);
}
/* Pass UTF-8 converted arguments to the main program */
int errorcode = _main(argc, mbargv);
/* Release UTF-8 arguments */
for (int i = 0; i < argc; i++) {
free(mbargv[i]);
}
/* Release the argument table */
free(mbargv);
return errorcode;
}
#else
int
main(int argc, char *argv[])
{
return _main(argc, argv);
}
#endif