How to Cd into a Directory Using Perl

How to cd in terminal using perl script by providing input from terminal?

Each process on a Linux server runs in an environment. The current working directory is one of the attributes of that environment.

When a new process starts (and your Perl program runs as a new process), it inherits the current environment from its parent process. The new process can then make whatever changes it wants to its new environment. It cannot, however, change its parent's environment. When a process ends, its environment is destroyed.

So, what happens here:

  • You have a process (your shell window, for example) which has its environment. The current working directory is... well, let's say your home directory.
  • You run your Perl program. That inherits a copy of the existing environment, with the current working directory set to your home directory.
  • You program changes directory to your new directory. This is in the subprocess environment. It does not affect the parent environment.
  • Your program ends and exits. The subprocess environment is destroyed.
  • You are back in your shell window environment. This environment hasn't changed. Therefore, your current working directory hasn't changed.

This is something that all Unix/Linux users have to find out for themselves at some point. You cannot write a program that changes the current working directory of its parent process.

regarding chdir in perl, how do I get back to the previous directory

Your question is not very clear. There are two different things I think you may be asking about. If I understand your setup, you do this:

$ cd a/b/c/d
$ perl stuff.pl

stuff.pl does chdir("e/f/g/h"). Now you want to go back to a/b/c/d. Correct?

Case 1:

You want to go back after the script is done. Since the script is executed in a subprocess, when you exit the subprocess you will be back where you were before you started the script. Nothing special needs to be done.

Case 2:

You want to go back before the script is done. In this case, you can remember the current directory:

#!/usr/bin/env perl

# remember the directory
my $curdir = `pwd`;
chdir("e/f/g/h");
# ...
# return back:
chdir($curdir);
# ...

Perl chdir fails with a glob pattern

chdir does not accept * and other expansion characters in the argument. Use glob or something similar for this to extract a single directory, then chdir to that. For example, this changes directory to the first /home/test/test1/test2/perl* it finds:

$dir = (glob "/home/test/test1/test2/perl*")[0];
# only change dir if any dir was found:
if (-d $dir) {
# fail if cannot change dir (or, even better, use autodie):
chdir $dir or die "Could not change to $dir: $!";
}

Perl change working directory of caller

What you want to do is not possible. The closest thing would be to write some bash that does what you want and then in the calling shell, source it instead of running it. Software cannot affect the shell that calls it.

finding a file in directory using perl script

Even though very feasible in Perl, this looks more appropriate in Bash:

#!/bin/bash

filename=$(find ~ -name "$1" )
wc -l "$filename"
curl .......

The main issue would of course be if you have multiple files data1, say for example /home/user/dir1/data1 and /home/user/dir2/data1. You will need a way to handle that. And how you handle it would depend on your specific situation.

In Perl that would be much more complicated:

#! /usr/bin/perl -w
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
if 0; #$running_under_some_shell

use strict;

# Import the module File::Find, which will do all the real work
use File::Find ();

# Set the variable $File::Find::dont_use_nlink if you're using AFS,
# since AFS cheats.

# for the convenience of &wanted calls, including -eval statements:
# Here, we "import" specific variables from the File::Find module
# The purpose is to be able to just type '$name' instead of the
# complete '$File::Find::name'.
use vars qw/*name *dir *prune/;
*name = *File::Find::name;
*dir = *File::Find::dir;
*prune = *File::Find::prune;

# We declare the sub here; the content of the sub will be created later.
sub wanted;

# This is a simple way to get the first argument. There is no
# checking on validity.
our $filename=$ARGV[0];

# Traverse desired filesystem. /home is the top-directory where we
# start our seach. The sub wanted will be executed for every file
# we find
File::Find::find({wanted => \&wanted}, '/home');
exit;

sub wanted {
# Check if the file is our desired filename
if ( /^$filename\z/) {
# Open the file, read it and count its lines
my $lines=0;
open(my $F,'<',$name) or die "Cannot open $name";
while (<$F>){ $lines++; }
print("$name: $lines\n");

# Your curl command here
}
}

You will need to look at the argument-parsing, for which I simply used $ARGV[0] and I do dont know what your curl looks like.

A more simple (though not recommended) way would be to abuse Perl as a sort of shell:

#!/usr/bin/perl
#
my $fn=`find /home -name '$ARGV[0]'`;
chomp $fn;
my $wc=`wc -l '$fn'`;
print "$wc\n";
system ("your curl command");

perl how to finish the script by 'cd $newdir'

You can't.

Any cd (or similar) you run in the perl script will affect only the perl script (or a sub-shell spawned from the perl script).

It can't affect the parent shell directly.

The only thing you could do would be to output the directory and then cd to that or similar. (e.g. cd "$(perl "$HOME"/import_script.pl -i someparameter)" && "$HOME/program2" . but realize that this means you can't output anything else to standard output from the perl script or it will confuse cd.)

Or have perl run the second command also, etc.



Related Topics



Leave a reply



Submit