I have a list of full file paths. All of the full file paths look like "/dir1/dir2/dir3/s..". I want to completely remove the s. from the filename. There is the possibility of a filename being plural, for example s.asdfs.cpp. I do not want to remove the second occurence of s. since that is part of the actual filename and not a reoccuring theme in every full file path in the list.
Running the following in shell works as I want it to:
echo /dir1/dir2/dir3/s.filenames.cpp | sed 's#\(.*\)\/s\.\([^\/]*\)#\1\/\2#g'
Gives the desired result of:
/dir1/dir2/dir3/filenames.cpp
But if I run the following in php:
$formatted_filename = exec("echo ".$filename." | sed 's#\(.*\)\/s\.\([^\/]*\)#\1\/\2#g'");
where
$filename = /dir1/dir2/dir3/s.filenames.cpp;
And then in my bash shell run
php -q script_name_that_contains_command_above.php > test.html
and refresh my firefox browser that displays test.html I get very strange results. In place of where this edited file path should be listed I get
<strange box>/<strange box>
where
<strange box>
is a small box with 2 rows and 2 columns consisting of 0's except for the bottom right cell. The first occurence has a 1 in the bottom right cell, and the second occurence has a 2 in the bottom right cell.
The sed command works, but php, or the exec command is interpreting it incorrectly I believe. Any ideas?
The solution for using exec with this particular regular expression was to use the php function, preg_replace()
preg_replace("/\/s/./", "/", $filename);
Related
I just cannot fathom how to get the PHP exec() or shell_exec() functions to treat a '*' character as a wildcard. Is there some way to properly encode / escape this character so it makes it through to the shell?
This is on windows (via CLI shell script if that matters, Terminal or a git-bash yields the same results).
Take the following scenario:
C:\temp\ contains a bunch of png images.
echo exec('ls C:\temp\*');
// output: ls: cannot access 'C:\temp\*': No such file or directory
Permissions is not the problem:
echo exec('ls C:\temp\exmaple.png');
// output: C:\temp\example.png
Therefore the * character is the problem and is being treated as a literal filename rather than a wildcard. The file named * does not exist, so from that point of view, it's not wrong...
It also does not matter if I use double quotes to encase the command:
echo exec("ls C:\temp\*");
// output: ls: cannot access 'C:\temp\*': No such file or directory
I have also tried other things like:
exec(escapeshellcmd('ls C:\temp\*'));
exec('ls C:\temp\\\*');
exec('ls "C:\temp\*"');
exec('ls "C:\temp\"*');
And nothing works...
I'm pretty confused that I cannot find any other posts discussing this but maybe I'm just missing it. At this point I have already worked around the issue by manually programming a glob loop and using the internal copy() function on each file individually, but it's really bugging me that I do not understand how to make the wildcard work via shell command.
EDIT:
Thanks to #0stone0 - The answer provided did not particularly answer my initial question but I had not tried using forward slashes in the path and when I do:
exec('ls C:/temp/*')
It works correctly, and as 0stone0 said, it only returns the last line of the output, which is fine since this was just for proof of concept as I was not actually attempting to parse the output.
Also, on a side note, since posting this question my system had been updated to Win11 22H2 and now for some reason the original test code (with the backslashes) no longer returns the "Cannot access / no file" error message. Instead it just returns an empty string and has no output set to the &$output parameter either. That being said, I'm not sure if the forward slashes would have worked on my system prior to the 22H2 update.
exec() only returns the last output line by default.
The wildcard probably works, but the output is just truncated.
Pass an variable by ref to exec() and log that:
<?php
$output = [];
exec('ls -lta /tmp/*', $output);
var_dump($output);
Without any additional changes, this returns the same as when I run ls -lta /tmp/* in my Bash terminal
That said, glob() is still the preferred way of getting data like this especcially since
You shouldn't parse the output of ls
So I need to found out if an upload from a user is images/ video and what type. I currently use
"filetype"=>system("file -i -b ".$_FILES['file']['tmp_name'])
which is inserted into my MongoDB collection via this
$s3file='http://'.$bucket.'.s3.amazonaws.com/'.$actual_image_name;
$collection = static::db()->media;
$datetime = time();
$mediaupload = array("owner"=>$_SESSION['user_information'][0]['_id'],"filelink"=>$s3file,"filetype"=>system("file -i -b ".$_FILES['file']['tmp_name']),"filesize"=>$size,"uploadtime"=>$datetime,"ownerid"=>$_SESSION["user_information"][0]['_id']);
$collection->insert($mediaupload);
$media = $collection->findOne($mediaupload);
However what I am noticing is it echos the result out to the PHP page - which is not what I need it to do. i know it is the system function because when I remove that function it does not echo the uploaded file type to the php code.
I am wondering therefor how can i still run that system file -i -b function and get it to include into the MongoDB database but not echo the result into the public php page return.
Try something like (for multi-line output)
exec("file -i -b ".$_FILES['file']['tmp_name'], $output);
array("filetype"=>$output);
It may look a little unorthodox, but exec uses its second input parameter as a way to pass the output information back to you - the output of file will be stored as an array into $output.
From the docs:
If the output argument is present, then the specified array will be
filled with every line of output from the command. Trailing
whitespace, such as \n, is not included in this array. Note that if
the array already contains some elements, exec() will append to the
end of the array. If you do not want the function to append elements,
call unset() on the array before passing it to exec().
If you simply want the first line from the output, use the simpler version:
array("filetype"=>exec("file -i -b ".$_FILES['file']['tmp_name']));
I have switched the system to exec() and that seems to of fixed my issue
I've read here and cannot really understand how to speed up my simple exec() which basically looks like this:
zcat access_log.201312011745.gz | grep 'id=6' | grep 'id2=10' | head -n10
I've added ini_set('memory_limit', 256); to the top of the PHP document, but the script still takes about 1 minute to run (contrasted with about near instant completion in Penguinet). What can I do to improve it?
I would try some of the following:
Change your exec to just run somethig simple, like
echo Hello
and see if it still takes so long - if it does, the problem is in the process creation and exec()ing area.
If that runs quickly, try changing the exec to something like:
zcat access_log.201312011745.gz > /dev/null
to see if it is the "zcat" slowing you down
Think about replacing the greps with a "sed" that quits (using "q") as soon as it finds what you are looking for rather than continuing all the way to end of file - since it seems (by your "head") you are only interested in the first few, not all occurrences of your strings. For example, you seem to be looking for lines that contain "id=6" and also "id2=10", so if you used "sed" like below, it may be faster because "sed" will print it and stop immediately the moment it finds a line with "id=6" followed by "id2=10"
zcat access_log.201312011745.gz | sed -n '/id=2.*id2=10/p;q'
The "-n" says "don't print, in general" and then it looks for "id=2" followed by any characters then "id2=10". If it finds that, it prints the line and the "q" makes it quit immediately without looking through to end of file. Note that I am assuming "id=2" comes before "id2=10" on the line. If that is not true, the "sed" will need additional work.
I am total noob in scripting, and try to find out where is the problem in my code. I have a text files with customer details, first line of the file is username, second is real name. This details i need to pass to php. First, I need to find oldest file in directory. I created bash script which returns customer username:
oldest=`ls -tr1 temp/data/*.details|head -1`
head -n1 $oldest
This finds odest file (temp/data/xxx.details) and returns username, let's say xxx.
Now, to the php:
$username = shell_exec('./oldest_order.sh');
$name = shell_exec('head -2 temp/data/'.$username.'.details | sed -n 2p');
I can get username in my php, with the first line: it's xxx, but second line does not work, However, if I change '.$username.' to xxx, it works, so problem is somewhere around this variable.
Please advice.
Perhaps there is a new-line or space at the end or the beginning.
You can check that by doing a var_dump($username);. That will give you the actual length of the string so that you can compare it with the length you think it should have.
If it is white-space at the beginning or the end, you can use:
$name = shell_exec('head -2 temp/data/'.trim($username).'.details | sed -n 2p');
I Just wanna to list all files and subdirectories and store this list in file ...
in MS-DOS, Linux and MAC OS, the command line -- .ls( or .dir) >> files.txt -- would give me what I want ...
But, how to make a php script run it ?
if I use (on php)
exec ('ls >> files.txt');
I will get a error like this:
Warning: Unexpected character in input: '' (ASCII=28) state=0 in /Applications/XAMPP/xamppfiles/htdocs/DjUtilities/makeLabels.php on line 29
...
please, any idea ???
The use of this will be to set labels with the musics in a cd, here, divided by directories...
I wanna to get any cd's (subdirectories) and list the files (the tracks) to make a label with the track list....
So, The initial idea was to create a file with these data and then, process the data to make the labels... any better way to do that will be very welcome !!
You can use 'opendir' and 'readdir' to do that, both native php commands...
It's not up to your 'exec(...)' code. Same code runs well in my environment.
<?php
exec('ls >> filelist.txt');
?>
And It's result.
$ cat filelist.txt
a.html
a.out
...(omitted)
So, It looks like your php file may has some weird syntax/characters on line 29. ( like wrong usage of backslashes )