Insert line number in all files in folder - linux

I have folder which contains more then 100 files. I want to insert line number into each file.
nl command gives output to standard output on terminal. But I want to add line number in all files of folder.
Can you suggest me how to do this?

Following on #Gianluca's answer, and using bash instead:
for i in *.c *.h ; do ( nl $i > $i.numbered ) && mv $i.numbered $i ; done
This replaces all files ending with .c or .h in the current directory with line-numbered versions.

Using tcsh you can do something like
foreach f (`ls *`)
nl $f >> $f.out
mv $f.out $f
end
You can delete them mv command if you don't want to rename the files
(try the script on a copy ;-) )

Related

Splitting a large directory into smaller ones in Linux

I have a large directory named as application_pdf which contains 93k files. My use-case is to split the directory into 3 smaller subdirectories (to a different location that the original large directory) containing around 30k files each.
Can this be done directly from the commandline.
Thanks!
Using bash:
x=("path/to/dir1" "path/to/dir2" "path/to/dir3")
c=0
for f in *
do
mv "$f" "${x[c]}"
c=$(( (c+1)%3 ))
done
If you have the rename command from Perl, you could try it like this:
rename --dry-run -pe 'my #d=("dirA","dirB","dirC"); $_=$d[$N%3] . "/$_"' *.pdf
In case you are not that familiar with the syntax:
-p says to create output directories, à la mkdir -p
-e says to execute the following Perl snippet
$d[$N%3] selects one of the directories in array #d as a function of the serially incremented counter $N provided to the snippet by rename
The output value is passed back to rename by setting $_
Remove the --dry-run if it looks good. Please run on a small directory with a copy of 8-10 files first, and make a backup before trying on all your 93k files.
Test
touch {0,1,2,3,4,5,6}.pdf
rename --dry-run -pe 'my #d=("dirA","dirB","dirC"); $_=$d[$N%3] . "/$_"' *.pdf
'0.pdf' would be renamed to 'dirB/0.pdf'
'1.pdf' would be renamed to 'dirC/1.pdf'
'2.pdf' would be renamed to 'dirA/2.pdf'
'3.pdf' would be renamed to 'dirB/3.pdf'
'4.pdf' would be renamed to 'dirC/4.pdf'
'5.pdf' would be renamed to 'dirA/5.pdf'
'6.pdf' would be renamed to 'dirB/6.pdf'
More for my own reference, but if you don't have the Perl rename command, you could do it just in Perl:
perl -e 'use File::Copy qw(move);my #d=("dirA","dirB","dirC"); my $N=0; #files = glob("*.pdf"); foreach $f (#files){my $t=$d[$N++%3] . "/$f"; print "Moving $f to $t\n"; move $f,$t}'
Something like this might work:
for x in $(ls -1 originPath/*.pdf | head -30000); do
mv originPath/$x destinationPath/
done

Bash script to get all file with desired extensions

I'm trying to write a bash script that if I pass a text file containing some extension and a folder returns me an output file with the list of all files that match the desired extension, searching recursively in all sub-directories
the folder is my second parameter the extension list file my first parameter
I have tried:
for i in $1 ; do
find . -name $2\*.$i -print>>result.txt
done
but doesn't work
As noted from in comment:
It is not a good idea to write to a hard coded file name.
The given example fixes only the given code from the OP question.
Yes of course, it is even better to call with
x.sh y . > blabla
and remove the filename from the script itself. But my intention is not to fix the question...
The following bash script, named as x.sh
#!/bin/bash
echo -n >result.txt # delete old content
while read i; do # read a line from file
find $2 -name \*.$i -print>>result.txt # for every item do a find
done <$1 # read from file named with first arg from cmdline
with an text file named y with following content
txt
sh
and called with:
./x.sh y .
results in a file result.txt which contents is:
a.txt
b.txt
x.sh
OK, lets give some additional hints as got from comments:
If the results fiel should not collect any other conntent from other results of the script it can be simplified to:
#!/bin/bash
while read i; do # read a line from file
find $2 -name \*.$i -print # for every item do a find
done <$1 >result.txt # read from file named with first arg from cmdline
And as already mentioned:
The hard coded result.txt could be removed and the call can be something like
./x.sh y . > result.txt
Give this one-liner command a try.
Replace /mydir with the folder to search.
Change the list of extensions passed as argument to the egrep command:
find /mydir -type f | egrep "[.]txt|[.]xml" >> result.txt
After the egrep, each extension should be separated with |.
. char must be escaped with [.]

Monitor directories and sub directories for file created and get the first 7 characters of file created?

I want to monitor a directories + sub dir and get the first 7 characters of file that created in the folder or sub folder. I'm using these codes for my problem :
inotifywait -mqr /path/ -e create |
while read path file ; do
line=$(head -c 7 $file) ;
echo $line ;
done;
but when I run the code it won't print only succeeded for some text file (first 7 character = "setruk"), and not print anythings for some text file (first 7 characters = "kukuryu"). Can anyone help me ? pleasee ?
For me, this is the output of inotifywait:
$ inotifywait -mqr . -e create
./test/ CREATE five
./test/ CREATE six
./test/ CREATE seven
I don't know if you get the CREATE part, but you're probably missing the path to the directory. You likely want:
inotifywait -mqr /path/ -e create |
while read path action file ; do
line=$(head -c 7 "$path$file") ;
echo $line ;
done;
If you don't have the CREATE part in the line, just change the head command to include the $path part of the filename:
line=$(head -c 7 "$path$file") ;
What's probably happening is that files in sub-directories are not getting their characters printed but files in the main directory are.

Copy text from multiple files, same names to different path in bash (linux)

I need help copying content from various files to others (same name and format, different path).
For example, $HOME/initial/baby.desktop has text which I need to write into $HOME/scripts/baby.desktop. This is very simple for a single file, but I have 2500 files in $HOME/initial/ and the same number in $HOME/scripts/ with corresponding names (same names and format). I want append (copy) the content of file in path A to path B (which have the same name and format), to the end of file in path B without erase the content of file in path B.
Example content of $HOME/initial/*.desktop to final $HOME/scripts/*.desktop. I tried the following, but it don't work:
cd $HOME/initial/
for i in $( ls *.desktop ); do egrep "Icon" $i >> $HOME/scripts/$i; done
Firstly, I would backup $HOME/initial and $HOME/scripts, because there is lots of scope for people misunderstanding your question. Like this:
cd $HOME
tar -cvf initial.tar initial
tar -cvf scripts.tar scripts
That will put all the files in $HOME/initial into a single tarfile called initial.tar and all the files in $HOME/scripts into a single tarfile called scripts.tar.
Now for your question... in general, if you want to put the contents of FileB onto the end of FileA, the command is
cat FileB >> FileA
Note the DOUBLE ">>" which means "append" rather than single ">" which means overwrite.
So, I think you want to do this:
cd $HOME/initial/baby.desktop
cat SomeFile >> $HOME/scripts/baby.desktop/SomeFile
where SomeFile is the name of any file you choose to test with. I would test that has worked and then, if you are happy with that, go ahead and run the same command inside a loop:
cd $HOME/initial/baby.desktop
for SOURCE in *
do
DESTINATION="$HOME/scripts/baby.desktop/$SOURCE"
echo Appending "$SOURCE" to "$DESTINATION"
#cat "$SOURCE" >> "$DESTINATION"
done
When the output looks correct, remove the "#" at the start of the penultimate line and run it again.
I solved it, if some people want learn how to resolve is very simple:
using Sed
I need only the match (or pattern) line "Icon=/usr/share/some_picture.png into $HOME/initial/example.desktop to other with same name and format $HOME/scripts/example.desktop, but I had a lot of .desktop files (2500 files)
cd $HOME/initial
STRING_LINE=`grep -l -R "Icon=" *.desktop`
for i in $STRING_LINE; do sed -ne '/Icon=/ p' $i >> $HOME/scripts/$i ; done
_________
If you need only copy all to other file with same name and format
using cat
cd $HOME/initial
STRING_LINE=`grep -l -R "Icon=" *.desktop`
for i in $STRING_LINE; do cat $i >> $HOME/scripts/$i ; done

UNIX\LINUX: How to add a directory text to each line inside a file?

UNIX\LINUX: How to add a directory text to each line inside a file?
NOTE: I am just using shell(CMD TOOL OF LINUX REDHAT EPIC) no other...
You see I have many log files(.txt.gz) and I was able to open all of them just by using:
foreach i (./*/*dumpfiles.txt.gz_*)
> foreach? zcat $i
> foreach? grep "-e" $i
> foreach? END
Meaning I am going through all those folders finding a file dumpfiles.txt.gz_
The the output is like:
0x4899252 move x -999
0x4899231 move y -0
0x4899222 find scribe
0x4899231 move x -999
etc..
The problem is that I need the directory to be set to each line of the file...
I could get the directory by the command pwd.
The question to my problem is how to add a directory name on each line of the file?
Example:
(directory) (per line of all files)
machine01 0x4899252 move x -999
machine01 0x4899231 move y -0
machine09 0x4899222 find scribe
machine09 0x4899231 move x -999
etc..
I tried using $ sed but I cant find the solution... :(
Thanks...
here's a little perl script that does what you ask for (input is the filename):
$file = shift;
$path = `pwd`;
chomp($path);
open(TRY, "< $file");
while ($line = <TRY>) { print ($path . $line);}
close(TRY);
of course this prints to the screen, but you can pour it to file and rename it at the end of the script to $file
if you want to run it on the entire dir and downyou can run
find . -exec scriptname {} \;
if you want it to be on the current dir only, you need to add a -maxdepth 1 flag to the find after the '.'
update:
this also works (with no script, just a shell line):
perl -pi -e 's/^/$ENV{PWD} /g'

Resources