basic question: using a variable content as directory name in Linux - bash

I want to make a new directory with the name of every zip file currently exists in a specific directory, in another one. I have written a 'for loop' for this purpose:
files=NL*.zip
for a in $files; do
b=echo $a;
sudo mkdir '/home/shokufeh/Desktop/normals/T1/"${b}"';
done
but it creates a directory named ${b} for the first round and make errors for next ones.
Could you please tell me what I should do?

You put your variable in simple quotes, there fore '${b}' will never be interpreted. Try this:
for a in NL*.zip; do
sudo mkdir "/home/shokufeh/Desktop/normals/T1/${a}";
done
No need for variables $files and $b.
To summarize, let's say var=3,
echo "$var" will display 3
echo '$var' will display $var
echo "'$var'" will display '3'
echo '"$var"' will display "$var"
Hopefully this makes sense. Quotes function like parentheses and brackets.

Related

Bash Parameter Expansion - get part of directory path

Lets say I have this variable
FILE=/data/tenant/dummy/TEST/logs/2020-02-03_16.20-LSTRM.log
I'm trying to get the name of the 4th sub directory, in this example TEST
job=${FILE%/*/*} # This gives me /data/tenant/dummy/TEST
Then
name=${job##*/}
This give me exactly what I want - Test
However when I try to use this in for loop like this:
for FILE in "/data/tenant/dummy/*/logs/*$year-*"; do
job=${FILE%/*/*}
echo $job # /data/tenant/dummy/TEST(and few other directories, so far so good)
name=${job##*/}
echo $name
done
The result of echo $name shows the list of files in my current directory I'm in instead of TEST
Main issue is the double quotes groups all files into a single long string:
for FILE in "/data/tenant/dummy/*/logs/*$year-*"
You can see this if you do something like:
for FILE in "/data/tenant/dummy/*/logs/*$year-*"
do
echo "+++++++++++++++++++"
echo "${FILE}"
done
This should print ++++++++++++++ once followed by a single line with a long list of file names.
To process the files individually remove the double quotes, eg:
for FILE in /data/tenant/dummy/*/logs/*$year-*
It's also good practice to wrap individual variable references in double quotes, eg:
job="${FILE%/*/*}"
echo "$job"
name="${job##*/}"
echo "$name"

Bulk Renaming Files isnt working for me

I am running a shell script on my mac, and i am getting a "No Such file or directory.
The input is: the replacement_name, and the working dir.
The output is: changing all files in the directory from $file to $newfilename
#!/bin/sh
echo "-------------------------------------------------"
echo "Arguments:"
echo "Old File String: $1"
echo "New File Name Head: $2"
echo "Directory to Change: $3"
echo "-------------------------------------------------"
oldname="$1"
newname="$2"
abspath="$3"
echo "Updating all files in '$abspath' to $newname.{extension}"
for file in $(ls $abspath);
do
echo $file
echo $file | sed -e "s/$oldname/$newname/g"
newfilename=$("echo $file| sed -e \"s/$oldname/$newname/g\"")
echo "NEW FILE: $newfilename"
mv $abspath/$file $abspath/$newfilename
done
It seems that it doesnt like assigning the result of my 1-liner to a variable.
old_filename_string_template.dart
test_template.dart
./bulk_rename.sh: line 16: echo old_filename_string.dart| sed -e "s/old_filename_string/test/g": No such file or directory
NEW FILE:
Test Information:
mkdir /_temp_folder
touch old_filename_string_template.a old_filename_string_template.b old_filename_string_template.c old_filename_string1_template.a old_filename_string1_template.b old_filename_string1_template.c old_filename_string3_template.a old_filename_string3_template.b old_filename_string3_template.c
./convert.sh old_filename_string helloworld /_temp_folder
The double quotes here make the shell look for a command whose name (filename, alias, or function name) is the entire string between the quotes. Obviously, no such command exists.
> newfilename=$("echo $file| sed -e \"s/old_filename_string/$1/g\"")
Removing the double quotes inside the parentheses and the backslashes before the remaining ones will fix this particular error.
The construct $(command sequence) is called a command substitution; the shell effectively replaces this string with the standard output obtained by evaluating command sequence in a subshell.
Most of the rest of your script has much too few quotes; so it's really unclear why you added them here in particular. http://shellcheck.net/ is a useful service which will point out a few dozen more trivial errors. Briefly, anything which contains a file name should be between double quotes.
Try to put double quotes outside backticks/subtitutions (not INSIDE backticks/substitutions like $("..."))
newfilename="$(....)"
By the way, please consider to use the package perl rename which already does this bulk file rename very well, with Perl regex style which is easier to use. This perl rename command maybe alreay available in your (Mac) distro. See intro pages.

Bash Script To Check for Duplicate File Names from Command Line Arguments

I'm working on a shell script that will copy all the files from the command line to a directory. If the command line arguments contain any duplicate files, I want to prompt the user to either overwrite the existing file (it should now be in the directory), don't copy it, or rename it and then copy it.
What is the best way to approach this problem?
Here's some pseudocode of what I'm thinking:
for var in "$#"
do
for file in "$dirName" #unsure about this syntax too
do
if [ file or directory with name "$fileName" exists]; then
prompt user with options #i can handle this part :)
else
mv $var $dirName
fi
done
done
You are overcomplicating things.
for var in "$#"
do
if [ -e "$dirname/$var" ]; then
prompt user with options #i can handle this part :)
else
mv "$var" "$dirName"
fi
done
Make sure you use adequate quoting everywhere, by the way. Variables which contain file names should basically always be double quoted.

Batch rename files using mv and sed within a for loop results in exit code 64 - How do I correct the script?

I am attempting to rename several hundred folders to remove numbers that are prefixed to the folder name. I seem to have gotten most of the way there, but my script does not quite work yet. When I echo the commands created by the script instead of running those commands, everything looks fine. The script:
for file in *
do
echo mv "'"$file"'" $(echo "'"$file"'" | sed 's/[0-9]\{1,3\} //')
done
returns many lines of:
mv '123 filename' 'filename'
mv '99 another name' 'another name'
. . . etc.
If I take one of those lines and use on the command line, the folder is renamed appropriately. If I remove the echo to actually run those mv commands, though, they do not work. Instead, mv prints out the usage reminder that comes when you incorrectly enter the command in some way.
Why do the output commands work individually but not within the for loop? How can I correct this script?
Your quoting looks oddball. The variable should be in double quotes, no more and no less.
Furthermore, you should avoid the brittle $(echo ... | sed ...); this can be accomplished in pure shell:
for f in *; do
g=${f#[0-9]}; g=${g#[0-9]}; g=${g#[0-9]}
echo mv "$f" "${g# }"
done
Run with sh -x if you want to verify that the echo gets correct quoting. Then remove the echo to actually move.
The reason the output worked when copy/pasted is that the second level of quoting was actually necessary when copying the output from echo. A (risky, convoluted) workaround would have been to replace echo with eval.

use bash $HOME in shell script

How to made bash to execute variable value.
For example, we have this code, where variable value was set in single quotes(!).
#!/bin/bash
V_MY_PATH='$HOME'
echo "$V_MY_PATH"
ls $V_MY_PATH
The output is
$HOME
ls: $HOME: No such file or directory
How to made bash to translate shell variable insto its value if there is some.
I want to add some code after V_MY_PATH='$HOME' to make output like echo $HOME.
It's something simple, but i'm stuck.
(NB: I know that with V_MY_PATH="$HOME", it works fine.)
EDIT PART:
I just wanted to make it simple, but I feel that some details are needed.
I'm getting parameter from a file. This part works good. I don't want to rewite it.
The problem is that when my V_MY_PATH contains a predefined variable (like $home) it's not treated like its value.
Remove the single quotes
V_MY_PATH='$HOME'
should be
V_MY_PATH=$HOME
you want to use $HOME as a variable
you can't have variables in single quotes.
Complete script:
#!/bin/bash
V_MY_PATH=$HOME
echo "$V_MY_PATH"
ls "$V_MY_PATH" #; Add double quotes here in case you get weird filenames
Output:
/home/myuser
0
05430142.pdf
4
aiSearchFramework-7_10_2007-v0.1.rar
etc.
use variable indirect reference so:
pete.mccabe#jackfrog$ p='HOME'
pete.mccabe#jackfrog$ echo $p
HOME
pete.mccabe#jackfrog$ ls ${p}
ls: cannot access HOME: No such file or directory
pete.mccabe#jackfrog$ ls ${!p}
bash libpng-1.2.44-1.el6 python-hwdata squid
...
pete.mccabe#jackfrog$
The ${!p} means take the value of $p and that value is the name of the variable who's contents I wish to reference
Use eval command:
#!/bin/bash
V_MY_PATH='$HOME'
echo "$V_MY_PATH"
eval ls $V_MY_PATH
You can use single or double quotes, and in your case, none if you prefer.
You have nothing telling bash what the variable is equal to. Maybe something like this? (unless I misunderstand what you are trying to do)
======================================================================
#!/bin/bash
#########################
# VARIABLES #
#########################
V_MY_PATH=home
#########################
# SCRIPT #
#########################
echo "What is your home path?"
read $home
echo "Your home path is $V_MY_PATH"
ls $V_MY_PATH
Of course you could also just remove the variable at the top and use:
echo "Your home path is $home"

Resources