I called a Function recursively using shellscript,but the function doesnt accept the arguments while calling function recusively,infinite loop runs - shell

I am trying to print the sub-file and sub directories of a Specific file. The case is, I will be giving the location of the root-folder directly.First it should print the files and directories of the root-folder,in-case of files , it should only print the name of the file and return .In-case of folders, it should print the folder name and traverse through that sub- folder and print the files and folders present in it . So the case is, if it is file then print the name of file and leave else if it is a folder present ,recursively traverse through the folder and print the contents inside and if you find sub-folder in this folder, again recursively traverse it till you find no folder present. I need to execute in shell-script language
I had writen the sample code for this in java. This is the code logic. I am trying the same logic in shellscript but whenever I call the function recursively,it runs a infinite loop in shell script
Java code :
import java.io.File;
import java.nio.file.Files;
public class Recursion
{
public static void fileRecursive(File root)
{
System.out.println(root.getName());
if(root.isFile())
{
return;
}
else
{
File[] files = root.listFiles();
for(File file : files)
{
fileRecursive(file);
}
}
}
public static void main(String args[])
{
File directoryPath = new File("/home/keshav/Main");
System.out.println("Root Folder : "+directoryPath.getName());
fileRecursive(directoryPath);
}
}
Shell-Script Code:
FileTraverse()
{
path=$dirname
if [ -f "$path" ];
then
return;
else
for dir in `ls $dirname`;
do
FileTraverse $dir
done
fi
}
echo "Enter Root directory name"
read dirname
FileTraverse $dirname

Analyzing your program, we can see:
You assign a value to the variable dirname only once (outside the function in the read statement), but never assign a new value for it. Every invocation of the function (including the recorsive ones) use the same value for this variable.
You call your function by passing a parameter, but you never actually use this parameter.
Solution: Inside the function do a
path=$1
as a first statement and in the function body, replace each occurance of dirname by path.

Related

How to glob and check multiple files in InstallBuilder?

I'm making installer program using VMware InstallBuilder (previously named Bitrock InstallBuilder), and need to ensure the non-existence of some files in target directory. Here I describe its logic in Perl fake code:
sub validate_target_dir
{
my $target_dir = shift;
# find all candidate check files
foreach my $file ( glob( "$target_dir/*_vol0.dat" ) )
{
my $fname = basename($file);
# fail if has any data file other than myproduct
if ($fname ne "myproduct_vol0.dat") { return 0; }
}
return 1;
}
However I don't know how to implement similar logic in InstallBuilder, as its findFile action don't return multiple matching files (only the first one).
At current, I find a somewhat twisted way to do it: implement the function in a shell script. InstallBuilder allows you to unpack contents programmatically, so I can pack the script into the installer package and unpack&run it at needed time.
I still seek if there's possible way that purely implemented by InstallBuilder itself.

Transactions for file operations in Laravel

In Laravel I can do database transactions by passing a closure to the DB::transaction function.
Does Laravel have any support for a similar feature for the File or Storage facade? Where the file operations are run in a transaction, with rollback in case a file operation fails?
I'm imagining something like
$files = ... // Something that returns a collection
File::transaction(function () use ($files) {
$files->each(function() {
File::move(....);
});
});
There is no built in way of doing it so you'd have to make an implementation yourself.
A simple method of achieving it would be
$fileName = ""; // or $fileNames ( array ) if multiple file uploads
$files = "" // to be used if you're going to update or delete files. Again if multiple file modifications then use array
try{
/* Just a note, but your new file could overwrite any existing files,
so before uploading, check if another file exists with same filename
And if it does, load that file and keep it in the $files variable
*/
// Upload File
$fileName = // name of uploaded file
$files = // Any existing file you're going to modify. Load the entire file data, not just the name
// Modify/Delete a file
}( \Exception $e ){
// Now delete the file using fileName or $fileNames if the variable is not empty
// If you modified/deleted any file, then undo those modifications using the data in $files ( if it's not empty )
}
In this method, existing files are loaded to memory, but if there are multiple large files, it might be better to move them to a temporary location instead, and move them back if any exception is thrown. Just don't forget to delete these temporary files if the file transaction is a success

How to use a function as a string while using matching pattern

I want to make use of functions to get the full path and directory name of a script.
For this I made two functions :
function _jb-get-script-path ()
{
#returns full path to current working directory
# + path to the script + name of the script file
return $PWD/${0#./*}
}
function _jb-get-script-dirname ()
{
return ${(_jb-get-script-path)##*/}
}
as $(_jb-get-script-path) should be replaced by the result of the function called.
However, I get an error: ${(_jb-get-script-path)##*/}: bad substitution
therefore i tried another way :
function _jb-get-script-path ()
{
return $PWD/${0#./*}
}
function _jb-get-script-dirname ()
{
local temp=$(_jb-get-script-path);
return ${temp##*/}
}
but in this case, the first functions causes an error : numeric argument required. I tried to run local temp=$(_jb-get-script-path $0) in case the $0 wasn't provided through function call (or i don't really know why) but it didn't change anything
I don't want to copy the content of the second fonction as i don't want to replicate code for no good reason.
If you know why those errors happen, I really would like to know why, and of course, if you have a better solution, i'd gladely hear it. But I'm really interessed in the resolution of this problem.
You need to use echo instead of return which is used for returning a numeric status:
_jb-get-script-path() {
#returns full path to current working directory
# + path to the script + name of the script file
echo "$PWD/${0#./*}"
}
_jb-get-script-dirname() {
local p="$(_jb-get-script-path)"
echo "${p##*/}"
}
_jb-get-script-dirname

Get all the names of the .txt files inside a directory

I'm having a problem getting just the names of the .txt files inside a directory.
I want to get all the names of all the .txt files inside my application's main directory and add them to a listbox. The code I'm using is working but it's returning the full directory while I only want the name of files. Here's the code:
String^ folder = Application::StartupPath ;
array<String^>^ file = Directory::GetFiles(folder, "*.txt");
for (int i=0; i<file->Length; i++)
{
listBox1->Items->Add(file[i] );
}
This is returning the full directory, for example: C:\programs\asd.txt
And I only want: asd.txt
How can I get just the name of the file?
You can use Path.GetFileName()
for (int i=0; i<file->Length; i++)
{
listBox1->Items->Add(Path::GetFileName(file[i]) );
}
You can use the basename() function.
e.g.
file = basename(Directory::GetFiles(folder, "*.txt");

Debugging code via input files in visual studio

I was wondering if there is a way of debugging your code without having to input data to the console every single time you run a program. Let's say I have a .in file with the input data and I would like to use them to run my code.
Is there any way to do so?
Thanks in advance
To pass data to standard in for the debugging sessions, you can use the standard pipe options to pass in data. By adding the file to the solution and setting it to "content" and "copy always" the file is automatically copied to the output directory, making it easier to "find it".
Well, you can specify arguments in your Main() block in your Console app:
static void Main(string[] args)
The above would be the header. Then you could parse those arguments and open a file (with absolute path) in the first parameter:
if (args.Length > 0) {
string fileName = args[0];
FileInfo fi = new FileInfo(fi);
Then assign those to variables after reading the text:
using (StreamReader sr = fi.OpenText())
{
string v1 = sr.ReadLine();
string v2 = sr.ReadLine();
int v3 = int.Parse(sr.ReadLine());
}
}
Then operate on those variables. The text file would contain the variable input on each line.
Reference(s) that might help:
http://msdn.microsoft.com/en-us/library/cb20e19t.aspx
http://msdn.microsoft.com/en-us/library/system.io.fileinfo.opentext(v=vs.110).aspx

Resources