How to compare two files and if found equal ask the user to delete duplicate file by using shell script?
up vote
2
down vote
favorite
I am learning linux and was given this problem as my homework but i can't solve this that how we can compare two files content in shell mode.
(Here, we can assume that both files having text content like this
for eg.
$cat > f1
this is file 1)
$ cat duplicate_file.sh
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
x=` wc newfile | cut -d" " -f2 `
if [` $x -eq 0 `]
then
rm -i $file2
fi
I made this program but this ain't working!! So, Any suggestions??
shell-script files
New contributor
add a comment |
up vote
2
down vote
favorite
I am learning linux and was given this problem as my homework but i can't solve this that how we can compare two files content in shell mode.
(Here, we can assume that both files having text content like this
for eg.
$cat > f1
this is file 1)
$ cat duplicate_file.sh
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
x=` wc newfile | cut -d" " -f2 `
if [` $x -eq 0 `]
then
rm -i $file2
fi
I made this program but this ain't working!! So, Any suggestions??
shell-script files
New contributor
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I am learning linux and was given this problem as my homework but i can't solve this that how we can compare two files content in shell mode.
(Here, we can assume that both files having text content like this
for eg.
$cat > f1
this is file 1)
$ cat duplicate_file.sh
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
x=` wc newfile | cut -d" " -f2 `
if [` $x -eq 0 `]
then
rm -i $file2
fi
I made this program but this ain't working!! So, Any suggestions??
shell-script files
New contributor
I am learning linux and was given this problem as my homework but i can't solve this that how we can compare two files content in shell mode.
(Here, we can assume that both files having text content like this
for eg.
$cat > f1
this is file 1)
$ cat duplicate_file.sh
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
x=` wc newfile | cut -d" " -f2 `
if [` $x -eq 0 `]
then
rm -i $file2
fi
I made this program but this ain't working!! So, Any suggestions??
shell-script files
shell-script files
New contributor
New contributor
New contributor
asked Nov 10 at 6:13
Hariom kushwaha
111
111
New contributor
New contributor
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
up vote
4
down vote
The immediate issue in your code is the syntax error on the line reading
if [` $x -eq 0 `]
The [
and ]
must be separated from the arguments within by a space character. Also, the command substitution on this line, `$x -eq 0`
, is nonsensical as it would try to run the value of $x
as a command.
You also have issues with non-quoting of your variable expansions, which disqualifies your script from working on filenames containing whitespace characters and filename globbing patterns.
The script also unconditionally clobbers the file newfile
needlessly (and would fail if newfile
was the name of an existing directory) and it lacks a #!
-line.
There is no point in asking the user interactively for file paths. It would be better for the user to be able to make use of the shell's filename completion on the command line and provide the pathnames to the files there as two operands:
$ ./script.sh some/path/file1 some/other/path/file2
If running the script in this way, the two pathnames will be available inside the script as "$1"
and "$2"
.
The cmp
utility can be used in this script without creating a temporary file. Instead of redirecting its output, make it quiet by using its -s
option (for "silent") and use its exit status to determine if the two files were identical or not.
The script would look like
#!/bin/sh
if cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
Or, shorter,
#!/bin/sh
cmp -s -- "$1" "$2" && rm -i -- "$2"
This would call rm -i
on the second of the two given pathnames if it referred to a file with identical contents as the first pathname. The --
in the cmp
and rm
commands is necessary to avoid interpreting a filename starting with a dash as a set of options.
The issue with this script, as with your own script, is that if you give it the same pathname twice, i.e. you compare a file against itself, then it will offer to remove it.
Therefore, we also need to make sure that the two pathnames refer to two different files.
You can do that by comparing the two pathname strings with each other:
#!/bin/sh
if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
This may be enough for most applications but does not take symbolic links into account. In some shells you can also use the non-standard -ef
test ("equal file") which tests whether two pathnames refer to the same file (same i-node number and device):
#!/bin/bash
if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
or,
#!/bin/bash
! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"
And with some sanity checks (also moving the -ef
test to the sanity checks section):
#!/bin/bash
if [ "$#" -ne 2 ]; then
# did not get exactly two arguments
printf 'Usage:nt%s file1 file2n' "$0" >&2
exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$1" -ef "$2" ]; then
printf '%s and %s refer to the same filen' "$1" "$2" >&2
exit 1
fi
cmp -s -- "$1" "$2" && rm -i -- "$2"
Note that quoting the variable expansions is important since it's not uncommon for pathnames to contain spaces (on macOS, this is very common). Double quoting variable expansions also stops them from being interpreted as shell globbing patterns (your code would, for example, not work on a file called *
). Also note the use of a #!
-line appropriate for the script.
If your homework assignment requires you to read the pathnames of the two files interactively, then do that with read -r
and with IFS
set to an empty string. This would allow you to read pathnames starting with whitespace characters and containing characters:
#!/bin/bash
IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2
if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$p1" -ef "$p2" ]; then
printf '%s and %s refer to the same filen' "$p1" "$p2" >&2
exit 1
fi
cmp -s -- "$p1" "$p2" && rm -i -- "$p2"
Related:
- Why does my shell script choke on whitespace or other special characters?
- Understanding "IFS= read -r line"
- ShellCheck.net
If you at some point need to check whether a file is empty, as in your own code, then don't call wc
on it (it is inefficient as it would have to read the whole file). Instead, use a -s
test:
if [ -s "$pathname" ]; then
printf '%s has non-zero sizen' "$pathname"
else
printf '%s is empty (or does not exist)n' "$pathname"
fi
See man test
on your system, or refer to the POSIX standard for this utility.
did U&L recently started offering Code Review tasks?
– iBug
2 days ago
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
2 days ago
add a comment |
up vote
3
down vote
First include shebang #!
at the top like #!/bin/bash
You are having two errors:
Instead of
cmp $file1 $file2 > newfile,
it should be
cmp -- "$file1" "$file2" > newfile
as these values of these variables may have spaces, tabs, newline (characters of $IFS
), *
, [
, ?
(wildcard characters) in them or may start with -
.
Second error:
Instead of
if [` $x -eq 0 `]
it should be
if [ "$x" -eq 0 ].
Otherwise you will get error
bash: 0: command not found.
Also if you are having whitespace or wildcards in the file names then it should be:
rm -i -- "$file2"
otherwise it can delete multiple files.
add a comment |
up vote
0
down vote
There are many ways to solve this, but I'll go with what you've started.
First, don't forget the lead off the script with the interpreter string ("shebang"):
#!/bin/bash
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
At this point you could test a couple of things:
- if newfile is not empty the files differ
if [ ! -s newfile ]; then
rm -i $file2
fi
- Test the exit code for cmp operation. If it is 0, the files match.
if [ `echo $?` == 0 ]; then
rm -i $file2
fi
Also, your wc command isn't quite working. Try running it outside of the script. Do you get the result you're expecting?
I thinkwc
command is working, when I tested it, the problem is incmp $file1 $file2 > newfile
command.
– Debian_yadav
2 days ago
1
Why not test withif cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...
– Kusalananda
2 days ago
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
The immediate issue in your code is the syntax error on the line reading
if [` $x -eq 0 `]
The [
and ]
must be separated from the arguments within by a space character. Also, the command substitution on this line, `$x -eq 0`
, is nonsensical as it would try to run the value of $x
as a command.
You also have issues with non-quoting of your variable expansions, which disqualifies your script from working on filenames containing whitespace characters and filename globbing patterns.
The script also unconditionally clobbers the file newfile
needlessly (and would fail if newfile
was the name of an existing directory) and it lacks a #!
-line.
There is no point in asking the user interactively for file paths. It would be better for the user to be able to make use of the shell's filename completion on the command line and provide the pathnames to the files there as two operands:
$ ./script.sh some/path/file1 some/other/path/file2
If running the script in this way, the two pathnames will be available inside the script as "$1"
and "$2"
.
The cmp
utility can be used in this script without creating a temporary file. Instead of redirecting its output, make it quiet by using its -s
option (for "silent") and use its exit status to determine if the two files were identical or not.
The script would look like
#!/bin/sh
if cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
Or, shorter,
#!/bin/sh
cmp -s -- "$1" "$2" && rm -i -- "$2"
This would call rm -i
on the second of the two given pathnames if it referred to a file with identical contents as the first pathname. The --
in the cmp
and rm
commands is necessary to avoid interpreting a filename starting with a dash as a set of options.
The issue with this script, as with your own script, is that if you give it the same pathname twice, i.e. you compare a file against itself, then it will offer to remove it.
Therefore, we also need to make sure that the two pathnames refer to two different files.
You can do that by comparing the two pathname strings with each other:
#!/bin/sh
if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
This may be enough for most applications but does not take symbolic links into account. In some shells you can also use the non-standard -ef
test ("equal file") which tests whether two pathnames refer to the same file (same i-node number and device):
#!/bin/bash
if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
or,
#!/bin/bash
! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"
And with some sanity checks (also moving the -ef
test to the sanity checks section):
#!/bin/bash
if [ "$#" -ne 2 ]; then
# did not get exactly two arguments
printf 'Usage:nt%s file1 file2n' "$0" >&2
exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$1" -ef "$2" ]; then
printf '%s and %s refer to the same filen' "$1" "$2" >&2
exit 1
fi
cmp -s -- "$1" "$2" && rm -i -- "$2"
Note that quoting the variable expansions is important since it's not uncommon for pathnames to contain spaces (on macOS, this is very common). Double quoting variable expansions also stops them from being interpreted as shell globbing patterns (your code would, for example, not work on a file called *
). Also note the use of a #!
-line appropriate for the script.
If your homework assignment requires you to read the pathnames of the two files interactively, then do that with read -r
and with IFS
set to an empty string. This would allow you to read pathnames starting with whitespace characters and containing characters:
#!/bin/bash
IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2
if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$p1" -ef "$p2" ]; then
printf '%s and %s refer to the same filen' "$p1" "$p2" >&2
exit 1
fi
cmp -s -- "$p1" "$p2" && rm -i -- "$p2"
Related:
- Why does my shell script choke on whitespace or other special characters?
- Understanding "IFS= read -r line"
- ShellCheck.net
If you at some point need to check whether a file is empty, as in your own code, then don't call wc
on it (it is inefficient as it would have to read the whole file). Instead, use a -s
test:
if [ -s "$pathname" ]; then
printf '%s has non-zero sizen' "$pathname"
else
printf '%s is empty (or does not exist)n' "$pathname"
fi
See man test
on your system, or refer to the POSIX standard for this utility.
did U&L recently started offering Code Review tasks?
– iBug
2 days ago
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
2 days ago
add a comment |
up vote
4
down vote
The immediate issue in your code is the syntax error on the line reading
if [` $x -eq 0 `]
The [
and ]
must be separated from the arguments within by a space character. Also, the command substitution on this line, `$x -eq 0`
, is nonsensical as it would try to run the value of $x
as a command.
You also have issues with non-quoting of your variable expansions, which disqualifies your script from working on filenames containing whitespace characters and filename globbing patterns.
The script also unconditionally clobbers the file newfile
needlessly (and would fail if newfile
was the name of an existing directory) and it lacks a #!
-line.
There is no point in asking the user interactively for file paths. It would be better for the user to be able to make use of the shell's filename completion on the command line and provide the pathnames to the files there as two operands:
$ ./script.sh some/path/file1 some/other/path/file2
If running the script in this way, the two pathnames will be available inside the script as "$1"
and "$2"
.
The cmp
utility can be used in this script without creating a temporary file. Instead of redirecting its output, make it quiet by using its -s
option (for "silent") and use its exit status to determine if the two files were identical or not.
The script would look like
#!/bin/sh
if cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
Or, shorter,
#!/bin/sh
cmp -s -- "$1" "$2" && rm -i -- "$2"
This would call rm -i
on the second of the two given pathnames if it referred to a file with identical contents as the first pathname. The --
in the cmp
and rm
commands is necessary to avoid interpreting a filename starting with a dash as a set of options.
The issue with this script, as with your own script, is that if you give it the same pathname twice, i.e. you compare a file against itself, then it will offer to remove it.
Therefore, we also need to make sure that the two pathnames refer to two different files.
You can do that by comparing the two pathname strings with each other:
#!/bin/sh
if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
This may be enough for most applications but does not take symbolic links into account. In some shells you can also use the non-standard -ef
test ("equal file") which tests whether two pathnames refer to the same file (same i-node number and device):
#!/bin/bash
if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
or,
#!/bin/bash
! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"
And with some sanity checks (also moving the -ef
test to the sanity checks section):
#!/bin/bash
if [ "$#" -ne 2 ]; then
# did not get exactly two arguments
printf 'Usage:nt%s file1 file2n' "$0" >&2
exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$1" -ef "$2" ]; then
printf '%s and %s refer to the same filen' "$1" "$2" >&2
exit 1
fi
cmp -s -- "$1" "$2" && rm -i -- "$2"
Note that quoting the variable expansions is important since it's not uncommon for pathnames to contain spaces (on macOS, this is very common). Double quoting variable expansions also stops them from being interpreted as shell globbing patterns (your code would, for example, not work on a file called *
). Also note the use of a #!
-line appropriate for the script.
If your homework assignment requires you to read the pathnames of the two files interactively, then do that with read -r
and with IFS
set to an empty string. This would allow you to read pathnames starting with whitespace characters and containing characters:
#!/bin/bash
IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2
if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$p1" -ef "$p2" ]; then
printf '%s and %s refer to the same filen' "$p1" "$p2" >&2
exit 1
fi
cmp -s -- "$p1" "$p2" && rm -i -- "$p2"
Related:
- Why does my shell script choke on whitespace or other special characters?
- Understanding "IFS= read -r line"
- ShellCheck.net
If you at some point need to check whether a file is empty, as in your own code, then don't call wc
on it (it is inefficient as it would have to read the whole file). Instead, use a -s
test:
if [ -s "$pathname" ]; then
printf '%s has non-zero sizen' "$pathname"
else
printf '%s is empty (or does not exist)n' "$pathname"
fi
See man test
on your system, or refer to the POSIX standard for this utility.
did U&L recently started offering Code Review tasks?
– iBug
2 days ago
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
2 days ago
add a comment |
up vote
4
down vote
up vote
4
down vote
The immediate issue in your code is the syntax error on the line reading
if [` $x -eq 0 `]
The [
and ]
must be separated from the arguments within by a space character. Also, the command substitution on this line, `$x -eq 0`
, is nonsensical as it would try to run the value of $x
as a command.
You also have issues with non-quoting of your variable expansions, which disqualifies your script from working on filenames containing whitespace characters and filename globbing patterns.
The script also unconditionally clobbers the file newfile
needlessly (and would fail if newfile
was the name of an existing directory) and it lacks a #!
-line.
There is no point in asking the user interactively for file paths. It would be better for the user to be able to make use of the shell's filename completion on the command line and provide the pathnames to the files there as two operands:
$ ./script.sh some/path/file1 some/other/path/file2
If running the script in this way, the two pathnames will be available inside the script as "$1"
and "$2"
.
The cmp
utility can be used in this script without creating a temporary file. Instead of redirecting its output, make it quiet by using its -s
option (for "silent") and use its exit status to determine if the two files were identical or not.
The script would look like
#!/bin/sh
if cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
Or, shorter,
#!/bin/sh
cmp -s -- "$1" "$2" && rm -i -- "$2"
This would call rm -i
on the second of the two given pathnames if it referred to a file with identical contents as the first pathname. The --
in the cmp
and rm
commands is necessary to avoid interpreting a filename starting with a dash as a set of options.
The issue with this script, as with your own script, is that if you give it the same pathname twice, i.e. you compare a file against itself, then it will offer to remove it.
Therefore, we also need to make sure that the two pathnames refer to two different files.
You can do that by comparing the two pathname strings with each other:
#!/bin/sh
if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
This may be enough for most applications but does not take symbolic links into account. In some shells you can also use the non-standard -ef
test ("equal file") which tests whether two pathnames refer to the same file (same i-node number and device):
#!/bin/bash
if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
or,
#!/bin/bash
! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"
And with some sanity checks (also moving the -ef
test to the sanity checks section):
#!/bin/bash
if [ "$#" -ne 2 ]; then
# did not get exactly two arguments
printf 'Usage:nt%s file1 file2n' "$0" >&2
exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$1" -ef "$2" ]; then
printf '%s and %s refer to the same filen' "$1" "$2" >&2
exit 1
fi
cmp -s -- "$1" "$2" && rm -i -- "$2"
Note that quoting the variable expansions is important since it's not uncommon for pathnames to contain spaces (on macOS, this is very common). Double quoting variable expansions also stops them from being interpreted as shell globbing patterns (your code would, for example, not work on a file called *
). Also note the use of a #!
-line appropriate for the script.
If your homework assignment requires you to read the pathnames of the two files interactively, then do that with read -r
and with IFS
set to an empty string. This would allow you to read pathnames starting with whitespace characters and containing characters:
#!/bin/bash
IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2
if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$p1" -ef "$p2" ]; then
printf '%s and %s refer to the same filen' "$p1" "$p2" >&2
exit 1
fi
cmp -s -- "$p1" "$p2" && rm -i -- "$p2"
Related:
- Why does my shell script choke on whitespace or other special characters?
- Understanding "IFS= read -r line"
- ShellCheck.net
If you at some point need to check whether a file is empty, as in your own code, then don't call wc
on it (it is inefficient as it would have to read the whole file). Instead, use a -s
test:
if [ -s "$pathname" ]; then
printf '%s has non-zero sizen' "$pathname"
else
printf '%s is empty (or does not exist)n' "$pathname"
fi
See man test
on your system, or refer to the POSIX standard for this utility.
The immediate issue in your code is the syntax error on the line reading
if [` $x -eq 0 `]
The [
and ]
must be separated from the arguments within by a space character. Also, the command substitution on this line, `$x -eq 0`
, is nonsensical as it would try to run the value of $x
as a command.
You also have issues with non-quoting of your variable expansions, which disqualifies your script from working on filenames containing whitespace characters and filename globbing patterns.
The script also unconditionally clobbers the file newfile
needlessly (and would fail if newfile
was the name of an existing directory) and it lacks a #!
-line.
There is no point in asking the user interactively for file paths. It would be better for the user to be able to make use of the shell's filename completion on the command line and provide the pathnames to the files there as two operands:
$ ./script.sh some/path/file1 some/other/path/file2
If running the script in this way, the two pathnames will be available inside the script as "$1"
and "$2"
.
The cmp
utility can be used in this script without creating a temporary file. Instead of redirecting its output, make it quiet by using its -s
option (for "silent") and use its exit status to determine if the two files were identical or not.
The script would look like
#!/bin/sh
if cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
Or, shorter,
#!/bin/sh
cmp -s -- "$1" "$2" && rm -i -- "$2"
This would call rm -i
on the second of the two given pathnames if it referred to a file with identical contents as the first pathname. The --
in the cmp
and rm
commands is necessary to avoid interpreting a filename starting with a dash as a set of options.
The issue with this script, as with your own script, is that if you give it the same pathname twice, i.e. you compare a file against itself, then it will offer to remove it.
Therefore, we also need to make sure that the two pathnames refer to two different files.
You can do that by comparing the two pathname strings with each other:
#!/bin/sh
if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
This may be enough for most applications but does not take symbolic links into account. In some shells you can also use the non-standard -ef
test ("equal file") which tests whether two pathnames refer to the same file (same i-node number and device):
#!/bin/bash
if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
or,
#!/bin/bash
! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"
And with some sanity checks (also moving the -ef
test to the sanity checks section):
#!/bin/bash
if [ "$#" -ne 2 ]; then
# did not get exactly two arguments
printf 'Usage:nt%s file1 file2n' "$0" >&2
exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$1" -ef "$2" ]; then
printf '%s and %s refer to the same filen' "$1" "$2" >&2
exit 1
fi
cmp -s -- "$1" "$2" && rm -i -- "$2"
Note that quoting the variable expansions is important since it's not uncommon for pathnames to contain spaces (on macOS, this is very common). Double quoting variable expansions also stops them from being interpreted as shell globbing patterns (your code would, for example, not work on a file called *
). Also note the use of a #!
-line appropriate for the script.
If your homework assignment requires you to read the pathnames of the two files interactively, then do that with read -r
and with IFS
set to an empty string. This would allow you to read pathnames starting with whitespace characters and containing characters:
#!/bin/bash
IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2
if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$p1" -ef "$p2" ]; then
printf '%s and %s refer to the same filen' "$p1" "$p2" >&2
exit 1
fi
cmp -s -- "$p1" "$p2" && rm -i -- "$p2"
Related:
- Why does my shell script choke on whitespace or other special characters?
- Understanding "IFS= read -r line"
- ShellCheck.net
If you at some point need to check whether a file is empty, as in your own code, then don't call wc
on it (it is inefficient as it would have to read the whole file). Instead, use a -s
test:
if [ -s "$pathname" ]; then
printf '%s has non-zero sizen' "$pathname"
else
printf '%s is empty (or does not exist)n' "$pathname"
fi
See man test
on your system, or refer to the POSIX standard for this utility.
edited 2 days ago
answered 2 days ago
Kusalananda
114k15218349
114k15218349
did U&L recently started offering Code Review tasks?
– iBug
2 days ago
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
2 days ago
add a comment |
did U&L recently started offering Code Review tasks?
– iBug
2 days ago
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
2 days ago
did U&L recently started offering Code Review tasks?
– iBug
2 days ago
did U&L recently started offering Code Review tasks?
– iBug
2 days ago
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
2 days ago
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
2 days ago
add a comment |
up vote
3
down vote
First include shebang #!
at the top like #!/bin/bash
You are having two errors:
Instead of
cmp $file1 $file2 > newfile,
it should be
cmp -- "$file1" "$file2" > newfile
as these values of these variables may have spaces, tabs, newline (characters of $IFS
), *
, [
, ?
(wildcard characters) in them or may start with -
.
Second error:
Instead of
if [` $x -eq 0 `]
it should be
if [ "$x" -eq 0 ].
Otherwise you will get error
bash: 0: command not found.
Also if you are having whitespace or wildcards in the file names then it should be:
rm -i -- "$file2"
otherwise it can delete multiple files.
add a comment |
up vote
3
down vote
First include shebang #!
at the top like #!/bin/bash
You are having two errors:
Instead of
cmp $file1 $file2 > newfile,
it should be
cmp -- "$file1" "$file2" > newfile
as these values of these variables may have spaces, tabs, newline (characters of $IFS
), *
, [
, ?
(wildcard characters) in them or may start with -
.
Second error:
Instead of
if [` $x -eq 0 `]
it should be
if [ "$x" -eq 0 ].
Otherwise you will get error
bash: 0: command not found.
Also if you are having whitespace or wildcards in the file names then it should be:
rm -i -- "$file2"
otherwise it can delete multiple files.
add a comment |
up vote
3
down vote
up vote
3
down vote
First include shebang #!
at the top like #!/bin/bash
You are having two errors:
Instead of
cmp $file1 $file2 > newfile,
it should be
cmp -- "$file1" "$file2" > newfile
as these values of these variables may have spaces, tabs, newline (characters of $IFS
), *
, [
, ?
(wildcard characters) in them or may start with -
.
Second error:
Instead of
if [` $x -eq 0 `]
it should be
if [ "$x" -eq 0 ].
Otherwise you will get error
bash: 0: command not found.
Also if you are having whitespace or wildcards in the file names then it should be:
rm -i -- "$file2"
otherwise it can delete multiple files.
First include shebang #!
at the top like #!/bin/bash
You are having two errors:
Instead of
cmp $file1 $file2 > newfile,
it should be
cmp -- "$file1" "$file2" > newfile
as these values of these variables may have spaces, tabs, newline (characters of $IFS
), *
, [
, ?
(wildcard characters) in them or may start with -
.
Second error:
Instead of
if [` $x -eq 0 `]
it should be
if [ "$x" -eq 0 ].
Otherwise you will get error
bash: 0: command not found.
Also if you are having whitespace or wildcards in the file names then it should be:
rm -i -- "$file2"
otherwise it can delete multiple files.
edited 2 days ago
Stéphane Chazelas
292k54547887
292k54547887
answered 2 days ago
Debian_yadav
1,0413922
1,0413922
add a comment |
add a comment |
up vote
0
down vote
There are many ways to solve this, but I'll go with what you've started.
First, don't forget the lead off the script with the interpreter string ("shebang"):
#!/bin/bash
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
At this point you could test a couple of things:
- if newfile is not empty the files differ
if [ ! -s newfile ]; then
rm -i $file2
fi
- Test the exit code for cmp operation. If it is 0, the files match.
if [ `echo $?` == 0 ]; then
rm -i $file2
fi
Also, your wc command isn't quite working. Try running it outside of the script. Do you get the result you're expecting?
I thinkwc
command is working, when I tested it, the problem is incmp $file1 $file2 > newfile
command.
– Debian_yadav
2 days ago
1
Why not test withif cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...
– Kusalananda
2 days ago
add a comment |
up vote
0
down vote
There are many ways to solve this, but I'll go with what you've started.
First, don't forget the lead off the script with the interpreter string ("shebang"):
#!/bin/bash
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
At this point you could test a couple of things:
- if newfile is not empty the files differ
if [ ! -s newfile ]; then
rm -i $file2
fi
- Test the exit code for cmp operation. If it is 0, the files match.
if [ `echo $?` == 0 ]; then
rm -i $file2
fi
Also, your wc command isn't quite working. Try running it outside of the script. Do you get the result you're expecting?
I thinkwc
command is working, when I tested it, the problem is incmp $file1 $file2 > newfile
command.
– Debian_yadav
2 days ago
1
Why not test withif cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...
– Kusalananda
2 days ago
add a comment |
up vote
0
down vote
up vote
0
down vote
There are many ways to solve this, but I'll go with what you've started.
First, don't forget the lead off the script with the interpreter string ("shebang"):
#!/bin/bash
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
At this point you could test a couple of things:
- if newfile is not empty the files differ
if [ ! -s newfile ]; then
rm -i $file2
fi
- Test the exit code for cmp operation. If it is 0, the files match.
if [ `echo $?` == 0 ]; then
rm -i $file2
fi
Also, your wc command isn't quite working. Try running it outside of the script. Do you get the result you're expecting?
There are many ways to solve this, but I'll go with what you've started.
First, don't forget the lead off the script with the interpreter string ("shebang"):
#!/bin/bash
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
At this point you could test a couple of things:
- if newfile is not empty the files differ
if [ ! -s newfile ]; then
rm -i $file2
fi
- Test the exit code for cmp operation. If it is 0, the files match.
if [ `echo $?` == 0 ]; then
rm -i $file2
fi
Also, your wc command isn't quite working. Try running it outside of the script. Do you get the result you're expecting?
answered 2 days ago
kevlinux
1542
1542
I thinkwc
command is working, when I tested it, the problem is incmp $file1 $file2 > newfile
command.
– Debian_yadav
2 days ago
1
Why not test withif cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...
– Kusalananda
2 days ago
add a comment |
I thinkwc
command is working, when I tested it, the problem is incmp $file1 $file2 > newfile
command.
– Debian_yadav
2 days ago
1
Why not test withif cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...
– Kusalananda
2 days ago
I think
wc
command is working, when I tested it, the problem is in cmp $file1 $file2 > newfile
command.– Debian_yadav
2 days ago
I think
wc
command is working, when I tested it, the problem is in cmp $file1 $file2 > newfile
command.– Debian_yadav
2 days ago
1
1
Why not test with
if cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...– Kusalananda
2 days ago
Why not test with
if cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...– Kusalananda
2 days ago
add a comment |
Hariom kushwaha is a new contributor. Be nice, and check out our Code of Conduct.
Hariom kushwaha is a new contributor. Be nice, and check out our Code of Conduct.
Hariom kushwaha is a new contributor. Be nice, and check out our Code of Conduct.
Hariom kushwaha is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f480903%2fhow-to-compare-two-files-and-if-found-equal-ask-the-user-to-delete-duplicate-fil%23new-answer', 'question_page');
}
);
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password