How to concatenate a list of strings in cmd? - list

Consider the one-liner of:
for %s in (str1 str2 str3) do #echo %s
if I could define an empty string then:
set "var=empty" & for %s in (str1 str2 str3) do #set "var=%var%, %s"
wold give me what I want. I tried the set "var=0:~1" thing from here:
set "var=0:~1" & for %s in (str1 str2 str3) do #set "var=%var%, %s"
but it does not work. What I want to have in the end is a string of str1, str2, str3 to be echoed.
P.S. I am aware of the for %s in (str1 str2 str3) do #(#Echo|#Set /p="%A, ") solution, but it does not behave the way I want. basically it prints multiple times to the stdout omiting the new-line, instead once which I require. I'm trying to use this command inside a unig_g("...") inside Scilab/ScicosLab which prints empty for that reason.

What you are trying to accomplish requires the use of delayed variable expansion. In a batch file you would normally turn this on with a SETLOCAL command but since you are using the command line you need to execute cmd.exe and use the appropriate option to turn delayed expansion on.
cmd /V:ON /C "set "var=" & (for %s in (str1 str2 str3) do #IF DEFINED var (#set "var=!var!, %s") else (set "var=%s")) & #echo !var!"

Related

Extracting .rar/.zip using c++

For no particular reason, I'm currently working on a program that extracts .zip/.rar files using system().
I currently have WinRar installed because winrar.exe is able to handle both .zip & .rar files.
int main()
{
vector<wstring> files;
if (ListFiles(L"folder", L"*", files))
{
string program = "\"C:\\Program Files\\WinRAR\\winrar.exe\"";
string args = "x -y";
string type = "*.*";
TCHAR dir[MAX_PATH];
GetCurrentDirectory(MAX_PATH, dir);
wstring current_directory(wstring(L"\"") + dir + wstring(L"\\"));
for (const auto& f : files)
{
if (wcscmp(PathFindExtension(f.c_str()), L".rar") == 0 ||
wcscmp(PathFindExtension(f.c_str()), L".zip") == 0)
{
string file = ws2s(f.c_str());
string output = "\"c:\\Users\\my name\\Desktop\\output\"";
string command = program + " " + args + " " + ws2s(current_directory) + file + "\"" + " " + type + " " + output;
cout << command << endl;
if (system(command.c_str()) != 0)
return GetLastError();
}
}
}
return 0;
}
Because I'm using the command line, and don't want spaces to be a problem I wrap what I can in quotation marks:
-- "C:/users/username/program files (x86)/" --
-- "folder/zipped folder.zip" vs folder/"zipped folder.zip" --
After building the complete command contained in command, I printed it out to the screen so I could Edit->Mark:
"C:\Program Files\WinRAR\winrar.exe" x -y "C:\Users\my name\Documents\Visual Studio 2013\Projects\extractor\folder\unzip.zip" *.* "c:\Users\my name\Desktop\output"
However, 'C:\Program' is not recognized as an internal or external command,
operable program or batch file. is what I'm met with after the system(command) call.
If I Copy & Paste the exact same command into Start->Command Prompt, it works like a dream.
How to extract ZIP files with WinRAR command line?
http://comptb.cects.com/using-the-winrar-command-line-tools-in-windows/
https://www.feralhosting.com/faq/view?question=36
Is there a way different way to invoke the system() call?
If there's not, how else can command line arguments be used?
I'd prefer to [avoid entirely] not use Boost:: or 3rd party libraries.
Thanks!
This is probably because of the quirky behavior of Command Prompt when it comes to quotation of arguments. Whenever you call system("\"arg1\" \"arg2\""), it is equivalent to calling:
cmd.exe /c "arg1" "arg2"
Because of the strange behavior as described in the linked post, this will not be interpreted correctly by Command Prompt. An extra set of quotes is needed:
cmd.exe /c ""arg1" "arg2""
For invoking executables, CreateProcess provides an alternative that gives you more control over the process. You'll still have to quote the arguments but the rules are a bit simpler as the Command Prompt is no longer in your way.

escaping a variable into a quote?

i'm trying to make a function that outputs n amount of colored spaces or " ". I specifically need it to be a quote string thing (not s) because I'm sending as an argument to the system() function.
is there a way that I can use a char variable inside a string.
I need it to function like this(I know it won't work):
system("echo -e \"\e[45m _myCharHere_ \"");
this way I can make the spaces (" ") any size I choose by multiplying the char by what ever integer I choose.
This is probably a stupid question, but I don't know all the technical programming terms for these operations etc; so I can't google it.
Thanks
You may use something like:
// Assuming mychar doesn't need escape sequence.
std::string command = std::string("echo -e \"\e[45m ") + myChar + " \"";
system(command.c_str());
Or as mentioned in comment, write directly (and here myChar can be special char):
std::cout << "\033[45m " << myChar;

Print a string with fprintf

I am having an issue with printing a string which im using for debug purposes.
I create the string like so:
//checker is int
std::stringstream buttonx;
buttonx << "Button" << checker << "_x";
Now i try to print it to my error.txt file
FILE * p;
p = fopen ("error.txt","w");
fprintf(p, "%s" , buttonx.str());
fclose(p);
The output is:
,æ0
Its different every time. I'm not sure whats going on was hopeing some could explain the mistake?
fopen is plain C and cannot handle std::string. You need to input a char*, which you can access by calling .c_str() on the string, like this:
fprintf(p, "%s", buttonx.str().c_str());
the function fprintf wants a null terminated string (a C string); you need the c_str() instead of yours:
buttonx.c_str()

Getting rid of newline in CString in C++

I have a html/xml document that is originally a CString and I want to get rid of all the newlines, essentially put everything into one line. I've tried converting it to std::String and using:
#include <algorithm>
#include <string>
str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
But it didn't work.
In order to stop your block of text looking odd, you'd want to replace the line breaks with a space. Make sure to replace both newline('\n') and carriage return('\r') characters.
CString str = "Line 1 Windows Style\r\n Line 2 Unix Style\n Line 3";
str.Replace('\r', " ");
str.Replace('\n', " ");
str.Replace(" ", " ");
You need only to use the method remove
CString str = _T("Test newline \nremove"), str2;
str.Remove('\n');
How about?
str.Replace("\n", "");
Documented here

c++ linux system command

I have the following problem:
I use in my program this function:
system("echo -n 60 > /file.txt");
it works fine.
But I don't want to have constant value. I do so:
curr_val=60;
char curr_val_str[4];
sprintf(curr_val_str,"%d",curr_val);
system("echo -n curr_val_str > /file.txt");
I check my string:
printf("\n%s\n",curr_val_str);
Yes,it is right.
but system in this case doesn't work and doesn't return -1. I just print string!
How can I transfer variable like integer that will be printed in file like integer, but don't string?
So I want to have variable int a and I want to print value of a with system function in file. A real path to my file.txt is /proc/acpi/video/NVID/LCD/brightness. I can't write with fprintf. I don't know why.
you cannot concatenate strings like you are trying to do. Try this:
curr_val=60;
char command[256];
snprintf(command, 256, "echo -n %d > /file.txt", curr_val);
system(command);
The system function takes a string. In your case it's using the text *curr_val_str* rather than the contents of that variable. Rather than using sprintf to just generate the number, use it to generate the entire system command that you require, i.e.
sprintf(command, "echo -n %d > /file.txt", curr_val);
first ensuring that command is large enough.
The command that is actually (erroneously) executed in your case is:
"echo -n curr_val_str > /file.txt"
Instead, you should do:
char full_command[256];
sprintf(full_command,"echo -n %d > /file.txt",curr_val);
system(full_command);
#define MAX_CALL_SIZE 256
char system_call[MAX_CALL_SIZE];
snprintf( system_call, MAX_CALL_SIZE, "echo -n %d > /file.txt", curr_val );
system( system_call );
man snprintf
The correct way would be similar to this:
curr_val=60;
char curr_val_str[256];
sprintf(curr_val_str,"echo -n %d> /file.txt",curr_val);
system(curr_val_str);
Just DON'T. :)
Why resort to system() for such a simple operation?
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int write_n(int n, char * fname) {
char n_str[16];
sprintf(n_str, "%d", n);
int fd;
fd = open(fname, O_RDWR | O_CREAT);
if (-1 == fd)
return -1; //perror(), etc etc
write(fd, n_str, strlen(n_str)); // pls check return value and do err checking
close(fd);
}
Have you considered using C++'s iostreams facility instead of shelling out to echo? For example (not compiled):
std::ostream str("/file.txt");
str << curr_val << std::flush;
Alternately, the command you pass to system must be fully formatted. Something like this:
curr_val=60;
std::ostringstream curr_val_str;
curr_val_str << "echo -n " << curr_val << " /file.txt";
system(curr_val_str.str().c_str());
Use snprintf to avoid security issues.
What about using std::string & std::to_string...
std::string cmd("echo -n " + std::to_string(curr_val) + " > /file.txt");
std::system(cmd.data());