Could not unlink [closed] - linux

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm totally puzzled with unlink() here:
my $file = "\"/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html\"";
unlink($file) or warn "Could not unlink $file: $!";
will throw
Could not unlink "/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html": No such file or directory
while the file actually exists:
$ ls -l "/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html"
-rw-rw-r-- 1 user user 413 Mar 25 13:41 /home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html
EDIT: I also tried:
my $file = "/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html";
my $file = '/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html';
my $file = "\'/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html\'";
Same error.
EDIT2: more tests as required by choroba
Testing the file existence with -f returns false.
Here's a hexdump of the real file name:
$ ls "/home/yasin/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html" | hexdump -c
0000000 / h o m e / y a s i n / D o c u
0000010 m e n t s / P r o g r a m m i n
0000020 g / P e r l / e x t r a c t e d
0000030 / P r u e b a c o n f o r m
0000040 a t e o H T M L / m s g - 2 5
0000050 7 5 - 4 . h t m l \n
000005a

The filename does not contain double quotes. Do not include them in the variable's value.
my $file = '/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html';
unlink $file or warn "Could not unlink $file: $!";

my $file = "\"/home/.../msg-2575-4.html\"";
unlink($file)
is the equivalent of doing
rm "\"/home/.../msg-2575-4.html\""
Obviously, the correct shell command is
rm "/home/.../msg-2575-4.html"
so you want
my $file = "/home/.../msg-2575-4.html";
unlink($file)
or
my $file = '/home/.../msg-2575-4.html';
unlink($file)
If that second rm command works, so does that Perl command.

Related

Why is my for loop not iterating in Linux Shell?

I am trying to run an alphabetical sequence in Linux shell. I believe my syntax is correct, but its not giving me each letter, but rather {a..z} all at once. Here is what I have:
COUNTER=0;
for X in {a..z};
do
# Make sure usb is mounted before trying anything
sudo mkdir /media/mounts/sd${X}1
sudo mount /dev/sd${X}1 /media/mounts/sd${X}1
# Find player number from Linux mount point
DATA_DIR=/media/mounts/sd${X}1;
PLAYER_FILE_PATH=`find $DATA_DIR -name "player.*"`;
PLAYER_FILE_ONLY=`basename -- $PLAYER_FILE_PATH`;
PLAYER_NUMBER=`echo "${PLAYER_FILE_ONLY##*.}"`;
# Make sure usb device exists and player number is not empty
if [ -n "$PLAYER_NUMBER" ] && [ $PLAYER_NUMBER -gt 0 ]
then
# Let user know which tracer was found
echo "$PLAYER_NUMBER was found, creating directory to store its .dat files" | tee -a $ERR_LOG_PATH;
echo "${PLAYER_NUMBER}: " >> $LOG_PATH;
let COUNTER++;
# Create directory for player number to dump .dat files and log any errors at output
sudo mkdir $DUMP_DIR/$PLAYER_NUMBER;
NUMBER_DATS=`ls $DATA_DIR/MountsData/*.dat | wc -l`;
DAT_COUNT_ARRAY[$PLAYER_NUMBER]=$NUMBER_DATS
echo "USB $PLAYER_NUMBER has $NUMBER_DATS .dat files";
echo "${NUMBER_DATS}\r\n" >> $LOG_PATH;
cp $DATA_DIR/MountsData/*.dat $DUMP_DIR/$PLAYER_NUMBER 2>> $ERR_LOG_PATH;
# Remove all .dat files directly from usb and log any errors at output
sudo rm $DATA_DIR/MountsData/*.dat 2>> $ERR_LOG_PATH;
fi
done
I get the resulting output:
mount: special device /dev/sd{a..z}1 does not exist
I have tried changing the variable names, capitalization, and referring to them as $X instead of ${X}. I am currently using a Raspberry Pi running Raspbian with a standard Raspbian shell. I ran some test to ensure syntax was right in the terminal and seems like the for loop structure is correct. Am I missing something?
you have to execute it with bash.
some os link sh to bash, but some of them link to other shell apps like the dash in ubuntu.
to check the linked app in your sh, try to execute this command:
file -h /bin/sh
You can write a portable function that will generate the list in a POSIX compatible way. For example to generate a range of ASCII characters from any character (with lower ASCII value) to any ASCII character, you can do:
genasciirange() {
[ -n "$1" -a -n "$2" ] || return 1
local a=$(LC_CTYPE=C printf '%d' "'$1")
local b=$(LC_CTYPE=C printf '%d' "'$2")
[ "$a" -lt "$b" -a "$a" -lt 256 -a "$b" -lt 256 ] || return 1
local c="$a"
while [ "$c" -le "$b" ]; do
printf " \\$(printf '%03o' "$c")"
c=$((c+1))
done
printf "\n"
}
(where -a is the older AND for conditions within [...], you can replace with [...] && [...] if you desire)
The conversion from character to ASCII value is handled by LC_CTYPE=C printf '%d' "'$somechar" and from ASCII value to character by converting to octal value and then outputting the escaped octal code, e.g. printf " \\$(printf '%03o' "$someasciival")"
Example Use/Output
genasciirange a z
a b c d e f g h i j k l m n o p q r s t u v w x y z
or for example:
genasciirange Q q
Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q
In your case, you can include the function and replace the brace-expansion with:
for X in $(genasciirange a z)
Using the jot Utility
A fairly common utility available is jot. It is simply an advanced seq that can generate sequential or random data. For example, for a-z you could do:
jot -s " " -w %c 26 a
a b c d e f g h i j k l m n o p q r s t u v w x y z
It is likely available for your Linux distribution already. If not, you can build from source athena-jot-9.0.orig.tar.gz from Ubuntu Source Package: athena-jot (9.0-7)
awk can be used as well.
Look things over and let me know if you have questions.

Does a second (inner) loop open a subprocess?

I have come to an interesting topic, while I was experimenting
recursive loops in a shell script.
First I came across interesting functionality of
for x in a b c d; do
for x in e f d h; do
a=test
done
echo $x
done
Always outputting letter h as variable $x. Which makes sense, as inner loop uses x as variable name too, and h would be the last one picked in such loop.
My concern is, does inner loops open a subprocess or how is the functionality guaranteed?
for x in a b c d; do
for x in e f d h; do
pstree $$
done
pstree $$
done
.. suggest in the output that no sub-processes are opened on nested loops.
I am probably a little bit stuck in a loop, but is there a good documentation how a shell operates loops? I would like to know how does shell interpret the loops so it's kept within one layer of instructions.
Modify your example in this way:
#! /bin/bash
set -x
for x in a b; do
: x=$x
for x in c d; do
: x=$x
a=test
done
echo $x
done
This outputs:
+ for x in a b
+ : x=a
+ for x in c d
+ : x=c
+ a=test
+ for x in c d
+ : x=d
+ a=test
+ echo d
d
+ for x in a b
+ : x=b
+ for x in c d
+ : x=c
+ a=test
+ for x in c d
+ : x=d
+ a=test
+ echo d
d
Now you can see, the inner loop modifies x after the outer loop. When you print x it has always the last value of the inner loop.

converting txt file to zip file in TCL

i convert zip binary file to base64 txt file using other code. Now I want to convert the base64 txt file back to zip file using below code. but the resultant zip file display error. How can I solve this
proc b64en str {
set bits $str
set tail {}
return [string map {
A 000000 B 000001 C 000010 D 000011 E 000100 F 000101
G 000110 H 000111 I 001000 J 001001 K 001010 L 001011
M 001100 N 001101 O 001110 P 001111 Q 010000 R 010001
S 010010 T 010011 U 010100 V 010101 W 010110 X 010111
Y 011000 Z 011001 a 011010 b 011011 c 011100 d 011101
e 011110 f 011111 g 100000 h 100001 i 100010 j 100011
k 100100 l 100101 m 100110 n 100111 o 101000 p 101001
q 101010 r 101011 s 101100 t 101101 u 101110 v 101111
w 110000 x 110001 y 110010 z 110011 0 110100 1 110101
2 110110 3 110111 4 111000 5 111001 6 111010 7 111011
8 111100 9 111101 + 111110 / 111111
} $bits]$tail
}
proc callme {file1 file2} {
set file1 [open $file1 r]
set file2 [open $file2 w+]
fconfigure $file2 -translation binary
fconfigure $file1 -buffering line
while {[gets $file1 data]>=0} {
set var $data
set nvar [string trimright $var = ]
set nvar [string trimright $nvar = ]
set var2 [b64en $nvar]
set var3 [binary format B* $var2]
puts $file2 $var3
}
close $file1
close $file2
}
set fp1 [lindex $argv 0]
set fp2 [lindex $argv 1]
callme $fp1 $fp2
The above code is working for txt to txt file
please help me.
Thanks
when in open resultant zip file it display this error
When you're writing binary data, I think you need to specify -nonewline, otherwise you'll have extra newline characters in the binary file, and the data will be corrupt.
puts -nonewline $file2 $var3

Restarting a job for supercomputer while looping a command for millions of files?

I'm using a supercomputer which is using the famous #PBS. My walltime is 48 hours and this is not enough to process million files.
My file names are like :
AAAAAA.pdb
DAAAAA.pdb
EAAAAA.pdb
FAAAAA.pdb
...
All possibles letters are "A D E F G H I K L M N P Q R S T V W Y".
I want to use a script like this :
for file in /dir/*
do
cmd [option] $file >> results.out
done
But I must use a restart for the wall time. With numbers I would have put a counter but with specific letters I don't know how to write the last file to start from this checkpoink. Like :
if [ -f next.seq ]; then
seq=`cat next.seq`
else
...
for file in /dir/seq
do
cmd [option] $file >> results.out
done
...
let seq=seq+1
echo $seq > next.seq

How to add a single special character randomly anywhere inside a string? Bash

I have this script that generates a random character between 8-16. I am confused as to how I would add a single random special character from a bank [! # # $ % ^ & * ( ) _ + ] anywhere randomly inside this string?
if [ $# -eq 0 ] then
pwdlen=$(((RANDOM % 9 ) +8))
spclen=$((RANDOM % 1))
char=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V X W Y Z)
chars=(~ ! # # $ % ^ & * - +)
#rand2=$random % 11
max=${#char[*]}
for i in `seq 1 $pwdlen`
do
let "rand=$RANDOM % $max"
str="${str}${char[$rand]}"
done
echo $str
exit 0
fi
teststring=foobarspam
specialchars='!##$%^&*()_+'
randomchar=${specialchars:RANDOM % ${#specialchars}:1}
randompos=$(( RANDOM % ( ${#teststring} + 1 ) ))
newstring=${teststring:0:randompos}${randomchar}${teststring:randompos}
You can use the following code.
#!/bin/bash
if [ $# -eq 0 ]; then
pwdlen=$(((RANDOM % 9 ) +8))
spclen=$((RANDOM % 1))
char=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V X W Y Z)
chars=('~' '!' '#' '#' '$' '%' '^' '&' '*' '-' '+')
#rand2=$random % 11
max=${#char[*]}
for i in `seq 1 $pwdlen`
do
let "rand=$RANDOM % $max"
str="${str}${char[$rand]}"
done
A=$(echo $str|wc -c) ## To get the count of
P=$((RANDOM % $A)) ## To get a random position of where to insert the character.
I=$((RANDOM % 11)) ## To get a random index number of chars array
C=${chars[$#]}
echo $str | sed 's!^\(.\{'$P'\}\).!\1\'"$C"'!' ## Inserting the special character to string in defined position
exit 0
fi
Output:
$ for i in `seq 1 10`;do ./test1;done
j^eh8BmD2H
0B01^1AN6EVw
Wu2$LLTILuDN8fSV
e^90gmHjksDo
eB7wa\#fmwf
NVAtJkmfqx~
JaHvD%uyO3rB
ncFrgyyz~UkZ
q0LLRHUNATM8DL
X%ARcXgyC1Do
I am not sure what script language are you using. I wrote a solution for you using PHP. If PHP is not what you are using, you should be able to convert the same logic to other languages and get the same results.
<?php
//This is the original string where you want to add a random character to
$org_string = 'This is My original String';
//calculates the length of the string
$org_length = strlen($org_string);
//find a random position
$pos = rand(0, $org_length-1);
//concatenate the first part of the string, random character, the remaining string
$final = substr($org_string, 0, $pos) . getOne() . substr($org_string, $pos);
//print the final value
echo $final;
//return a random string
function getOne(){
//the following string is 12 characters in length. it is all available characters that you want to select from
$str = '!##$%^&*()_+';
//return a random character
return $str[rand(0, 11)];
}
?>

Resources