What is wrong with my list naming code? - bash

I would like to change the file name from Sub****_Ses1 to HU_TT_12_****_UU;
(**** numbered from 0001 to 1600)
I did the below
#!/bin/sh
#Change file name
Subj_id=/Users/dave/biomark/dat
cd Subj_id
for abcd in Sub****_Ses1; do
mv Sub$a$b$c$d_Ses1 HU_TT_12_$a$b$c$d_UU;
done

for and wildcards don't work like this. Use cut to extract the number.
$ touch Sub000{1,2,3,4}_Ses1
$ for f in Sub????_Ses1
do
abcd=$(echo $f | cut -b4-7)
mv $f HU_TT_12_${abcd}_UU
done
$ ls HU_TT_12_000*
HU_TT_12_0001_UU HU_TT_12_0002_UU HU_TT_12_0003_UU HU_TT_12_0004_UU

You can use sed and mv
#!/bin/bash
set -x
Subj_id=/Users/dave/biomark/dat
cd $Subj_id
for i in Sub*_Ses1 ; do
#echo $i|sed -r 's/^.*\([[:digit:]]{4}\).*/HU_TT_12_\1_UU/'
mv $i $(echo $i|sed -rn 's/^.*([[:digit:]]{4}).*/HU_TT_12_\1_UU/ p')
done

Related

How to find symlinks in a directory that points to another

I need to write a bash script that finds and lists symlinks from one directory (lets say some "Directory1") but only the ones pointing to files in certain another directory (lets say "Directory2"). I can`t use "find".
I have tried something like this but it's apparently wrong:
if [[ -d $1 ]]&&[[ -d $2 ]]
then
current_dir='pwd'
cd $1
do
for plik in *
if[[-L $file] && ["$(readlink -- "$file")" = "$2"] ]
then
#ls -la | grep ^l
echo "$(basename "$file")"
fi
done
fi
How about a simple ls with grep :
ls -l Directory1/ | grep "\->" | grep "Directory2"
I have found a solution:
for file1 in $_cat1/* do
if [ -L $file1]; then
dir1="$(dirname `readlink -f $file1`)"
dir2="$(dirname `readlink -f $_cat2`)"
if [dir1 == dir2]
echo $dir1
fi
fi
done

Files missing in directory A but present in directory B

I am trying to create:
a list containing files present in a but missing in b
a list containing files present in b but missing in a
This is my code so far:
#!/bin/sh
set -e
A_DIR_1=/tmp/1
A_DIR_2=/tmp/2
A_DIR_3=/tmp/3
B_DIR_1=/tmp/1
B_DIR_2=/tmp/2
B_DIR_3=/tmp/3
for i in {1..3}
do
A="A_DIR_$i"
B="B_DIR_$i"
if [ d ${!A} ]; then
bash -c 'diff -u <(find "${!B}" |sed "s:${!B}::") <(find "${!A}" |sed "s:${!A}::") |sed "/^+\//!d; s::${!A}/:"' >> /tmp/fileA
bash -c 'diff -u <(find "${!A}" |sed "s:${!A}::") <(find "${!B}" |sed "s:${!A}::") |sed "/^+\//!d; s::${!B}/:"' >> /tmp/fileB
fi
done
However, when I run it, I get the following error: find: cannot search : No such file or directory'. Why is this? The directories definitely exist.
mm, imho your code is difficult.
If I've understood you clearly, that can help:
Prepare:
mkdir /tmp/dir1
mkdir /tmp/dir2
touch /tmp/dir1/test{1..12}
touch /tmp/dir2/test{1..15}
touch /tmp/dir1/test{22..25}
Code:
#!/bin/bash
dir1=/tmp/dir1
dir2=/tmp/dir2
diff_result=$(diff -u "${dir1}" "${dir2}")
echo "${diff_result}" | grep "${dir1}" | awk '{print $NF}' > /tmp/files_only_in_dir1
echo "${diff_result}" | grep "${dir2}" | awk '{print $NF}' > /tmp/files_only_in_dir2
Output:
$ cat /tmp/files_only_in_dir1
test22
test23
test24
test25
$ cat /tmp/files_only_in_dir2
test13
test14
test15

rename file names work in command prompt but not in bash script

I'm trying to rename commands in a bash script. If I run for example:
echo /home/scientist/mySalesData/campaignData_1482386214.24417.csv | sed 's/\(.*\)\(_.*\)/mv \"&" \"\1.csv\"/' | bash
It works fine and gives me campaignData.csv in the directory /home/scientist/mySalesData/ .
However, if I put this in a bash script as follows:
for f in /home/scientist/SalesData/*; do
if [ -f "$f" ];
cp "$f" /home/scientist/SalesForce/SalesData/Backups/
echo $f$ | sed 's/\(.*\)\(_.*\)/mv \"&" \"\1.csv\"/' | bash |
fi
done
I get:
mv: cannot stat '/home/scientist/SalesData/campaignData_1482386214.24417.csv$': No such file or directory
Any help would be much appreciated!
cd "$srcdir"
for f in *; do
if [ -f "$f" ]; then
cp "./$f" "$dstdir/${f%_*}.csv"
fi
done
The % is the strip shortest suffix pattern operator.
You have a trailing $ here:
echo $f$
remove that (and quote the expansion):
echo "$f"
You could use here string too:
sed ... <<<"$f"

Renaming Multiples Files To delete first portion of name

I have a list of files like so :
10_I_am_here_001.jpg
20_I_am_here_003.jpg
30_I_am_here_008.jpg
40_I_am_here_004.jpg
50_I_am_here_009.jpg
60_I_am_here_002.jpg
70_I_am_here_005.jpg
80_I_am_here_006.jpg
How can I rename all the files in a directory, so that I can drop ^[0-9]+_ from the filename ?
Thank you
Using pure BASH:
s='10_I_am_here_001.jpg'
echo "${s#[0-9]*_}"
I_am_here_001.jpg
You can then write a simple for loop in that directory like this:
for s in *; do
f="${s#[0-9]*_}" && mv "$s" "$f"
done
Using rename :
rename 's/^[0-9]+_//' *
Here's another bash idea based on files ending .jpg as shown above or whatever>
VonBell
#!/bin/bash
ls *.jpg |\
while read FileName
do
NewName="`echo $FileName | cut -f2- -d "_"`"
mv $FileName $NewName
done
With bash extended globbing
shopt -s extglob
for f in *
do
[[ $f == +([0-9])_*.jpg ]] && mv "$f" "${f#+([0-9])_}"
done

Rename folder name in bash

I need to rename the following folders:
d_001_d
d_001_h
d_005_d
d_005_h
d_007_d
d_007_h
In:
d_a_d
d_a_h
d_b_d
d_b_h
d_c_d
d_c_h
So basically each code number correspond to a name(letter). I tried with the
sed command and a for loop with an array but I'm not able to get exactly what I
want.
Thanks for help
bos:$ ls
d_001_d d_001_h d_005_d d_005_h d_007_d d_007_h
bos:$ for x in * ; do mv $x $(echo $x | sed -e 's/001/a/;s/005/b/;s/007/c/') ; done
bos:$ ls
d_a_d d_a_h d_b_d d_b_h d_c_d d_c_h
$ ls
d_001_d d_001_h d_005_d d_005_h d_007_d d_007_h
$ ls | awk -F_ -v OFS=_ 'BEGIN{d["001"]="a"; d["005"]="b"; d["007"]="c"}; {old=$0; $2=d[$2]; printf("mv %s %s\n", old, $0)}' | bash
$ ls
d_a_d d_a_h d_b_d d_b_h d_c_d d_c_h
If the directory names are all the same length, you can use this:
#!/bin/bash
for DIR in `ls */ -d`
do
INDEX=${DIR:2:3}
case $INDEX in
001)
LETTER="a"
;;
005)
LETTER="b"
;;
007)
LETTER="c"
;;
esac
mv "$DIR" ${DIR/$INDEX/$LETTER}
done
Without hardcoding the number->char mappings:
chr() { [[ ${1} -lt 256 ]] || return 1; printf \\$(printf '%03o' $1); }
printf "%s\n" d_001_d d_001_h d_005_d d_005_h d_007_d d_007_h |
while read name; do
prefix=${name%%_*}
suffix=${name##*_}
[[ $name =~ ([0-9]+) ]] && num=$((96+10#${BASH_REMATCH[1]}))
printf -v new_name "%s_%s_%s" $prefix $(chr $num) $suffix
echo $new_name
done
outputs
d_a_d
d_a_h
d_e_d
d_e_h
d_g_d
d_g_h
chr function courtesy this answer
With the perl rename tool you can rename with regex:
rename -n 'y/[157]/[abc]/;s/00//' d_00?_?
d_001_d renamed as d_a_d
d_001_h renamed as d_a_h
d_005_d renamed as d_b_d
d_005_h renamed as d_b_h
d_007_d renamed as d_c_d
d_007_h renamed as d_c_h
Omit the -n if the test with -n(ot really) yields a fine result.

Resources